home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Games / Hugo / Library / hugolib.h < prev    next >
Text File  |  1997-04-29  |  120KB  |  5,247 lines

  1. !----------------------------------------------------------------------------
  2. !
  3. !            HUGO Library v2.3.2 by Kent Tessman (c) 1995-1997
  4. !                     for use with Hugo Compiler v2.3
  5. !
  6. !----------------------------------------------------------------------------
  7.  
  8. #version 2.3
  9.  
  10. constant BANNER "Written using Hugo v2.3 by Kent Tessman (c) 1995-1997"
  11. constant HUGO_VERSION   "v2.3"
  12.  
  13. !----------------------------------------------------------------------------
  14. ! RESERVED PROPERTIES:
  15. !----------------------------------------------------------------------------
  16.  
  17. !\ The first 6 are pre-defined by the compiler:
  18.  
  19. property name                           ! property 0:  basic object name
  20. property before $additive $complex      ! pre-verb routines
  21. property after  $additive $complex      ! post-verb routines
  22. property noun                           ! noun(s) for referring to object
  23. property adjective                      ! adjective(s) describing object
  24. property article                        ! "a", "an", "some", etc.
  25. \!
  26.  
  27. property nouns alias noun               !
  28. property adjectives alias adjective     !
  29. property preposition                    ! "in", "inside", "outside of", etc.
  30. property prep alias preposition         !
  31. property pronoun "it"                   ! "he", "him", "his", "himself"
  32. property pronouns alias pronoun         !   (or equivalent)
  33. property short_desc                     ! basic "X is here" description
  34. property initial_desc                   ! same as above, before obj. is moved
  35. property long_desc                      ! detailed description
  36. property found_in                       ! in case of multiple parents
  37. property type                           ! to identify the type of object
  38. property size 10                        ! for holding/inventory purposes
  39. property capacity                       !  "          "            "
  40. property holding                        !  "          "            "
  41. property reach                          ! for limiting accessible objects
  42. property list_contents                  ! to override normal listing routine
  43. property in_scope                       ! actor(s) which can access an object
  44. property parse_rank                     ! for matching similarly named objects
  45. property exclude_from_all               ! i.e., exclude from multi-obj. verbs
  46.  
  47. ! The following apply only to room objects:
  48. property n_to                           !
  49. property ne_to                          !
  50. property e_to                           !
  51. property se_to                          !
  52. property s_to                           ! If the player can move from one 
  53. property sw_to                          ! room to another in direction X,
  54. property w_to                           ! X_to holds the object number of the
  55. property nw_to                          ! second room.
  56. property u_to                           !
  57. property d_to                           !
  58. property in_to                          !
  59. property out_to                         !
  60. property cant_go                        ! message if a move is invalid
  61. property extra_scenery                  ! unimportant words/objects in desc.
  62. property each_turn                      ! a routine called each turn
  63.  
  64. ! The following apply only to non-room objects:
  65. property door_to alias n_to             ! for handling "Enter <object>"
  66. property key_object alias ne_to         ! if lockable, what is the key?
  67. property when_open alias e_to           ! desc. for openable objects
  68. property when_closed alias se_to        !   "    "     "        "
  69. property ignore_response alias s_to     ! for unfriendly characters
  70. property order_response alias sw_to     ! for giving orders to characters
  71. property contains_desc alias w_to       ! instead of "X contains...", etc.
  72. property inv_desc alias nw_to           ! for inventory listing only
  73. property desc_detail alias u_to         ! parenthetical detail (ObjectIs)
  74.  
  75. property misc                           ! miscellaneous use
  76.  
  77.  
  78. !----------------------------------------------------------------------------
  79. ! RESERVED ATTRIBUTES:
  80. !----------------------------------------------------------------------------
  81.  
  82. attribute known                         ! set once an object is known about
  83. attribute moved                         !  "  once an object is moved
  84. attribute visited alias moved           !  "  once a room is visited
  85. attribute static                        !  "  when object cannot be taken
  86. attribute plural                        !  "  for plural objects
  87. attribute living                        !  "  if object is a character
  88. attribute female                        !  "  if character is female
  89. attribute openable                      !  "  if object can be opened
  90. attribute open                          !  "  if object is open
  91. attribute lockable                      !  "  if object can be locked
  92. attribute locked                        !  "  if object is locked
  93. attribute unfriendly                    ! for characters
  94. attribute light                         ! set if an object is/provides light
  95. attribute readable                      !  "  if object can be read
  96. attribute switchable                    !  "  if object can be turned on/off
  97. attribute switchedon                    !  "  if object is on
  98. attribute clothing                      !  "  if object can be worn
  99. attribute worn                          !  "  if object is being worn
  100. attribute mobile alias worn             !  "  if object may be moved around
  101. attribute enterable                     !  "  if object may be entered
  102. attribute container                     !  "  if things can be placed ON obj.
  103. attribute platform                      !  "  if things can be placed IN obj.
  104.                     !     ("container" and "platform" are
  105.                     !      mutually exclusive)
  106. attribute hidden                        !  "  if object isn't listed
  107. attribute quiet                         !  "  if container/platform is quiet
  108.                     !     (contents not initially listed)
  109. attribute transparent                   !  "  if object is not opaque
  110.  
  111. attribute workflag                      ! for library use
  112. attribute already_listed alias workflag 
  113.  
  114. attribute special                       ! for miscellaneous use
  115.  
  116.  
  117. !----------------------------------------------------------------------------
  118. ! RESERVED GLOBALS:
  119. !----------------------------------------------------------------------------
  120.  
  121. !\ The first 10 are pre-defined by the compiler:
  122.  
  123. global object                           ! direct object of a verb action
  124. global xobject                          ! indirect object
  125. global self                             ! self-referential object
  126. global words                            ! total number of words
  127. global player                           ! the player object
  128. global actor                            ! player, or a char. (for scripts)
  129. global location                         ! location of the player object
  130. global verbroutine                      ! the verb routine
  131. global endflag                          ! if non-false, run EndGame
  132. global prompt                           ! for input line
  133. global objects                          ! total number of objects
  134. global linelength                       ! with current printing configuration
  135. global pagelength                       !  "      "       "          "
  136. \!
  137.  
  138. global player_person = 2                ! first (1), second (2), or third (3)
  139.  
  140. global MAX_SCORE                        ! total possible score
  141. global FORMAT                           ! contains bitmap of format masks
  142. global DEFAULT_FONT                     ! 0=monospaced normal text
  143. global STATUSTYPE                       ! 0=none, 1=score/turns, 2=time
  144. global DISPLAYTYPE                      ! 0=text, 1=graphics
  145. global UNDO_OFF                         ! overrides undo when true
  146.  
  147. global counter                          ! elapsed turns (or time, as desired)
  148. global score                            ! accumulated score
  149. global verbosity                        ! for room descriptions
  150. global list_nest                        ! used by ListObjects
  151. global light_source                     ! in location
  152. global event_flag                       ! set when something happens
  153. global speaking                         ! if the player is talking to a char.
  154. global old_location                     ! whenever location changes
  155. global obstacle                         ! if something is stopping the player
  156. global list_count                       ! number of unlisted objects
  157. global need_newline                     ! true when newline should be printed
  158. global override_indent                  ! true if no indent should be printed
  159. global best_parse_rank                  ! for matching similarly named objects
  160. global customerror_flag                 ! true after CustomError is called
  161.  
  162. #ifclear NO_SCRIPTS
  163. constant MAX_SCRIPTS      16            !
  164. constant MAX_SCRIPT_STEPS 32            !
  165. global number_scripts                   ! for object scripts
  166. array scriptdata[48]                    !
  167. array setscript[1024]                   !
  168. #endif
  169.  
  170. global MAX_RANK                         ! allow for up to 10 levels of 
  171. array ranking[10]                       ! player ranking (as a default)
  172.  
  173. global it_obj                           !
  174. global them_obj                         !
  175. global him_obj                          ! to reference objects via pronouns
  176. global her_obj                          !
  177. array replace_pronoun[4]                !
  178.  
  179. constant MAX_WORDS 32                   ! in a parsed input line
  180. array oldword[MAX_WORDS]                ! for "again" command
  181.  
  182. global general                          ! for general use
  183.  
  184.  
  185. !----------------------------------------------------------------------------
  186. ! COLOR CONSTANTS AND GLOBALS
  187. !----------------------------------------------------------------------------
  188.  
  189. enumerate                               ! colors 0 to 17
  190. {
  191.     BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, WHITE
  192.     DARK_GRAY, LIGHT_BLUE, LIGHT_GREEN, LIGHT_CYAN,
  193.     LIGHT_RED, LIGHT_MAGENTA, YELLOW, BRIGHT_WHITE
  194.     DEF_FOREGROUND, DEF_BACKGROUND
  195. }
  196.  
  197. global TEXTCOLOR      = DEF_FOREGROUND  ! normal text color
  198. global BGCOLOR        = DEF_BACKGROUND  ! normal background color
  199. global SL_TEXTCOLOR   = BRIGHT_WHITE    ! statusline text color
  200. global SL_BGCOLOR     = BLUE            ! statusline background color
  201.  
  202.  
  203. !----------------------------------------------------------------------------
  204. ! PRINTING FORMAT MASKS
  205. !
  206. ! The following are bitmasks added/subtracted from the FORMAT global
  207. ! to affect text/list output.  Combine formats using '+' or '|' as in:
  208. !
  209. !       FORMAT = LIST_F | GROUPPLURALS_F | ...
  210. !----------------------------------------------------------------------------
  211.  
  212. enumerate start = 1, step *2
  213. {
  214.     LIST_F                  ! print itemized lists, not sentences
  215.     NORECURSE_F             ! do not recurse object contents
  216.     NOINDENT_F              ! do not indent listings
  217.     DESCFORM_F              ! alternate room desc. formatting
  218.     GROUPPLURALS_F          ! list plurals together where possible
  219.  
  220. ! For internal (library) use:
  221.  
  222.     INVENTORY_F             ! list as player inventory
  223.     FIRSTCAPITAL_F          ! capitalize first article
  224.     ISORARE_F               ! print "is" or "are" at the start
  225.     ISORAREHERE_F           ! print "is here" or "are here" last
  226.     USECHARNAMES_F          ! before listing contents
  227.     TEMPLIST_F              ! used if LIST_F must be overridden
  228. }
  229.  
  230. global INVENTORY_MASK = 0       ! may be set by DoInventory
  231.  
  232.  
  233. !----------------------------------------------------------------------------
  234. ! FONT STYLE BITMASKS
  235. !
  236. ! Used with the Font routine to set or change the font style.  Combine
  237. ! settings using '+' or '|', as in:
  238. !
  239. !       Font(BOLD_ON | ITALIC_OFF | ...)
  240. !----------------------------------------------------------------------------
  241.  
  242. #ifclear NO_FONTS
  243. enumerate start = 1, step *2
  244. {
  245.     BOLD_ON, BOLD_OFF,
  246.     ITALIC_ON, ITALIC_OFF,
  247.     UNDERLINE_ON, UNDERLINE_OFF,
  248.  
  249.     PROP_ON, PROP_OFF               ! proportional printing
  250. }
  251. #endif
  252.  
  253.  
  254. !----------------------------------------------------------------------------
  255. ! ADDITIONAL CONSTANTS (AND GLOBALS)
  256. !----------------------------------------------------------------------------
  257.  
  258. constant UP_ARROW       11              ! special keystrokes
  259. constant DOWN_ARROW     10
  260. constant LEFT_ARROW      8
  261. constant RIGHT_ARROW    21
  262. constant ESCAPE_KEY     27
  263. constant ENTER_KEY      13
  264.  
  265. constant AND_WORD       "and"           ! for language translation
  266. constant ARE_WORD       "are"
  267. constant HERE_WORD      "here"
  268. constant IN_WORD        "in"
  269. constant IS_WORD        "is"
  270. constant ON_WORD        "on"
  271.  
  272. constant FILE_CHECK     4660            ! for readfile/writefile blocks
  273.  
  274. global INDENT_SIZE =  2                 ! for paragraph formatting
  275. global AFTER_PERIOD = "  "              ! double-space after period
  276.  
  277.  
  278. !----------------------------------------------------------------------------
  279. ! SYNONYMS, COMPOUNDS, AND REMOVALS
  280. !----------------------------------------------------------------------------
  281.  
  282. synonym "and" for "~and"
  283. synonym "except" for "~except"
  284. synonym "but" for "~except"
  285. synonym "all" for "~all"
  286. synonym "everything" for "~all"
  287. synonym "any" for "~any"
  288. synonym "either" for "~any"
  289. synonym "oops" for "~oops"
  290. synonym "o" for "~oops"
  291. synonym "mine" for "my"
  292. synonym "myself" for "me"
  293. synonym "herself" for "her"
  294. synonym "himself" for "him"
  295. synonym "themselves" for "them"
  296.  
  297. compound "mr", "."
  298. compound "mrs", "."
  299. compound "dr", "."
  300. compound "st", "."
  301. compound "off", "of"
  302. compound "out", "of"
  303. compound "on", "to"
  304. compound "in", "to"
  305.  
  306. removal "a", "an", "the", "some", "of"
  307.  
  308.  
  309. !----------------------------------------------------------------------------
  310. object nothing "nothing"                ! OBJECT 0:  the great granddaddy
  311. {}
  312.  
  313.  
  314. !----------------------------------------------------------------------------
  315. ! EndGame(end_type)
  316. ! called by the engine via EndGame(end_type) when endflag is not false 
  317. ! (endflag is cleared previous to calling); return false to terminate
  318. !
  319. ! Default responses (in PrintEndGame):  1 = win, 2 = die, 3 = no resp.
  320.  
  321. routine EndGame(end_type)
  322. {
  323.     local r
  324.     
  325.     PrintStatusLine                 ! update one last time
  326.     PrintEndGame(end_type)          ! print appropriate ending message
  327.  
  328. :AskAgain
  329.  
  330.     Message(&EndGame, 1)    ! ask to RESTART, RESTORE, (UNDO), or QUIT
  331.     
  332.     r = -1
  333.     
  334.     while true
  335.     {
  336.         GetInput
  337.         select word[1]
  338.             case "restart"
  339.             {
  340.                 if restart
  341.                     {r = true
  342.                     PrintStatusline}
  343.                 else:  Message(&DoRestart, 2)   ! failed
  344.                 break
  345.             }
  346.             case "restore"
  347.             {
  348.                 if restore
  349.                     {r = true
  350.                     PrintStatusline
  351.                     DescribePlace(location)}
  352.                 else:  Message(&DoRestore, 2)   ! failed
  353.                 break
  354.             }
  355. #ifclear NO_UNDO
  356.             case "undo", "u"
  357.             {
  358.                 if not UNDO_OFF
  359.                 {
  360.                     if undo
  361.                         {r = true
  362.                         PrintStatusLine
  363.                         DescribePlace(location)}
  364.                     else
  365.                         Message(&DoUndo, 1)  ! failed
  366.                 }                
  367.                 else
  368.                     Message(&DoUndo, 1)
  369.                 break
  370.             }
  371. #endif
  372.             case "quit", "q"
  373.                 {r = 0
  374.                 break}
  375.  
  376.         Message(&EndGame, 2)    ! ask again (more succinctly)
  377.     }
  378.  
  379.     if r = -1:  jump AskAgain
  380.  
  381.     return r
  382. }
  383.  
  384. routine PrintEndGame(end_type)
  385. {
  386.     Font(BOLD_ON)
  387.     select end_type
  388.         case 1:  print "\n*** YOU'VE WON THE GAME! ***"
  389.         case 2:  
  390.         {
  391.             if player_person = 2
  392.                 print "\n*** YOU HAVE DIED ***"
  393.             else
  394.                 print "\n*** "; CThe(player); \
  395.                     MatchPlural(player, "has", "have"); \
  396.                     " died! ***"
  397.         }
  398.     Font(BOLD_OFF)
  399.     PrintScore(true)
  400. }
  401.  
  402. !----------------------------------------------------------------------------
  403. routine PrintScore(end_of_game)
  404. {
  405.     if STATUSTYPE = 1 and MAX_SCORE
  406.     {
  407.         if end_of_game:  print ""
  408.         print "You ";
  409.         if not end_of_game
  410.             print "have ";
  411.         print "scored a total of ";
  412.         print number score; " out of "; number MAX_SCORE;
  413.         if ranking[0] ~= ""
  414.         {
  415.             print ", giving you the rank of ";
  416.             
  417.             ! A complicated formula, since only 
  418.             ! integer division is allowed: 
  419.             !
  420.             print ranking[(score*100)/MAX_SCORE*MAX_RANK/100]
  421.         }
  422.         print "."
  423.     }
  424. }
  425.  
  426. !----------------------------------------------------------------------------
  427. ! Parse is called by the engine without parameters after input but before
  428. ! any grammar matching; returning true signals the engine to reparse the
  429. ! existing input (in case it has been changed)
  430. !
  431. ! The engine parser is responsible for splitting the input line into the
  432. ! word[] array, removing removals, replacing synonyms, and combining
  433. ! compounds.
  434. !
  435. ! This Parse routine is then called to take care of:
  436. !       - picking out extra_scenery words
  437. !       - checking for an "again" command
  438. !       - rewording imperatives to "<Name>, <command>"
  439. !       - renaming pronouns to objects
  440. !       - changing "then <do something else>" into a new command
  441. !
  442. ! Control then returns to the engine for grammar matching and, if that is
  443. ! successful, calling of the matched verb routine.
  444.  
  445. routine Parse
  446. {
  447.     local a, n
  448.     local reparse
  449.  
  450.     best_parse_rank = 0             ! reset each parser cycle
  451.     list_nest = 0
  452.  
  453.     if nothing ~= 0                 ! best place to check this
  454.         print "[WARNING:  Objects/classes defined before library]"
  455.  
  456. ! The following, devised by Jim Newland, checks to see if the player        
  457. ! input refers to an unnecessary item of scenery (for example) which is
  458. ! nonetheless mentioned in the location description.
  459.  
  460.     for (a=2; a<=words and word[a]~=""; a++)
  461.     {
  462.         if Inlist(location, extra_scenery, word[a])
  463.         {
  464.             Message(&Parse, 1)
  465.             word[1] = ""            ! force ParseError(0)
  466.             words = 0
  467.             customerror_flag = true
  468.             return true
  469.         }
  470.     }
  471.     
  472.     if PreParse:  reparse = true            ! easily replaceable routine
  473.  
  474.     ! Last player-specified object
  475.     if object:  AssignPronoun(object)
  476.  
  477.     ! To repeat last command
  478.     if (word[1] = "again" or word[1] = "g") and words = 1
  479.     {
  480.         for (a=1; a<=oldword[0]; a++)
  481.             word[a] = oldword[a]
  482.         words = oldword[0]
  483.         reparse = true
  484.         jump LeaveParse
  485.     }
  486.  
  487. ! Reword imperatives given as "Tell Bob to do something" as "Bob, do 
  488. ! something" so that the engine automatically reroutes them to SpeakTo
  489.  
  490.     elseif word[1] = "tell", "order", "instruct", "ask", "command"
  491.     {
  492.         for (a=1; a<=words and word[a]~=""; a++)
  493.         {
  494.             if word[a] = "to"
  495.             {
  496.                 DeleteWord(a)   ! "to"
  497.                 DeleteWord(1)   ! "tell", "order", etc.
  498.                 reparse = true
  499.                 break
  500.             }
  501.         }
  502.     }
  503.  
  504.     local count, number_pronouns
  505.     for (count=1; count<=words and word[count]~=""; count++)
  506.     {
  507.         select word[count]
  508.  
  509.             ! Rename pronouns to appropriate objects
  510.             case "it", "them", "him", "her"
  511.             {
  512.                 select word[count]
  513.                     case "it":   a = it_obj
  514.                     case "them": a = them_obj
  515.                     case "him":  a = him_obj
  516.                     case "her":  a = her_obj
  517.  
  518.                 n = SetObjWord(count, a)
  519.                 replace_pronoun[number_pronouns] = a
  520.                 number_pronouns++
  521.                 if n > 1
  522.                     count = count + (n - 1)
  523.                 reparse = true
  524.             }
  525.  
  526.             ! Allow for "then..." and "and then..."
  527.             case "then"
  528.             {
  529.                 word[count] = "."       ! end of this command
  530.                 if word[count-1] = "~and"
  531.                     DeleteWord(count-1)
  532.                 reparse = true
  533.                 break
  534.             }
  535.     }
  536.  
  537.     if number_pronouns > 0          ! print name(s) of assumed object(s)
  538.     {
  539.         Message(&Parse, 2)      ! "Assuming you mean..."
  540.         for (count = 0; count < number_pronouns; count++)
  541.         {
  542.             if count > 0
  543.             {
  544.                 if number_pronouns > 2
  545.                     print ",";
  546.                 if count = number_pronouns - 1
  547.                     print " "; AND_WORD; 
  548.             }
  549.             print " ";
  550.             
  551.             if replace_pronoun[count].name = ""
  552.                 The(nothing)
  553.             else
  554.                 The(replace_pronoun[count])
  555.         }
  556.         if number_pronouns > 1
  557.             Message(&Parse, 3)      ! ", respectively"
  558.         print ".)"
  559.     }
  560.  
  561. #ifset USE_PLURAL_OBJECTS
  562.     if ParsePluralObjects:  reparse = true
  563. #endif
  564.  
  565.     ! Store current command for future reference
  566.     for (a=1; a<=words and a<MAX_WORDS; a++)
  567.         oldword[a] = word[a]
  568.     oldword[a] = ""
  569.     oldword[0] = --a
  570.  
  571. :LeaveParse
  572.     
  573. #ifset DEBUG
  574.     if debug_flags & D_PARSE
  575.     {
  576.         for (a=1; a<=words and word[a]~=""; a++)
  577.             print "["; word[a]; "] ";
  578.         print newline
  579.     }
  580. #endif
  581.  
  582.     return reparse
  583. }
  584.  
  585. routine PreParse                        ! to be REPLACED if needed
  586. {}
  587.  
  588. routine SetObjWord(a, obj)      ! inserts unique name of <obj> at word <a>
  589. {
  590.     local i, n
  591.     
  592.     if obj.adjective                ! Allowing multiple adjectives...
  593.     {
  594.         n = obj.#adjectives
  595.         if n > 4 {n = 4}        ! ...(up to 4)...
  596.  
  597.         if n > 1:  InsertWord(a, n-1)
  598.         for (i=1; i<=n; i++)
  599.         {
  600.             word[a] = obj.adjective #i
  601.             a++
  602.         }
  603.     }
  604.     
  605.     if obj.noun                     ! ...and 1 noun (obj.noun #1)
  606.     {       
  607.         if n:  InsertWord(a)
  608.         word[a] = obj.noun
  609.         a++ : n++
  610.     }
  611.     
  612.     return n
  613. }
  614.  
  615. routine InsertWord(n, b)                ! inserts <b> words at position <n>
  616. {
  617.     local i
  618.     
  619.     if words+1 >= MAX_WORDS:  return
  620.  
  621.     if b = 0:  b = 1
  622.  
  623.     for (i=words+b; i>n; i--)
  624.         word[i] = word[i-b]
  625.     words = words + b
  626.  
  627.     return b
  628. }
  629.  
  630. routine DeleteWord(n, b)                ! deletes <b> words at position <n>
  631. {
  632.     local i
  633.  
  634.     if b = 0:  b = 1
  635.  
  636.     if (words < b) or (n + b >= MAX_WORDS):  return
  637.  
  638.     for (i=n; i<=words-b; i++)
  639.         word[i] = word[i+b]
  640.     word[words] = ""
  641.     words = words - b
  642.  
  643.     return b
  644. }
  645.  
  646. routine ObjWord(wd, obj)                ! returns adjective or noun if <wd> 
  647. {                                       ! is either for <obj>
  648.     if InList(obj, noun, wd)
  649.         return noun
  650.  
  651.     if InList(obj, adjective, wd)
  652.         return adjective
  653.  
  654.     return false                    ! didn't match either
  655. }
  656.  
  657. !----------------------------------------------------------------------------
  658. ! ParseError(errornumber, object)
  659. ! prints an appropriate error message; if called by the engine, signals the
  660. ! engine to produce the default message by returning false
  661. !
  662. ! (Note:  If <errornumber> is equal to or greater than 100, CustomError
  663. ! is called instead.  REPLACE CustomError for cases where custom error 
  664. ! messages are desired for user parsing routines.  Do not call CustomError
  665. ! directly.)
  666.  
  667. routine ParseError(errornumber, obj)
  668. {
  669.     if errornumber >= 100
  670.     {
  671.         CustomError(errornumber, obj)
  672.         word[1] = ""            ! force ParseError(0)
  673.         words = 0
  674.         customerror_flag = true
  675.         return true
  676.     }
  677.     if customerror_flag
  678.     {
  679.         customerror_flag = 0    ! CustomError already printed error
  680.         return true
  681.     }
  682.     
  683.     select errornumber
  684.         
  685.         case 1
  686.             print CThe(player); " can't use the word \""; \
  687.                 parse$; "\"."
  688.  
  689.         case 3
  690.             print CThe(player); " can't "; parse$; " multiple
  691.                 objects."
  692.  
  693.         case 5
  694.             print CThe(player); \
  695.                 MatchPlural(player, "hasn't", "haven't"); \
  696.                 "seen any \""; parse$; "\", nor"; \
  697.                 IsorAre(player, true); " "; The(player); \
  698.                 " likely to, even if such a thing exists."
  699.  
  700.         case 6
  701.             print "That doesn't make any sense."
  702.  
  703.         case 9
  704.         {
  705.             print "Nothing to ";
  706.             if verbroutine
  707.                 print parse$; "."
  708.             else:  print "do."
  709.         }
  710.         
  711.         case 10
  712.         {
  713.             print CThe(player); \
  714.               MatchPlural(player, "hasn't", "haven't"); " seen ";
  715.             if obj is living
  716.                 print "anybody";
  717.             else:  print "anything";
  718.             print " like that."
  719.         }
  720.         
  721.         case 11
  722.         {
  723.             if not ObjectisKnown(obj)
  724.                 ParseError(10, obj)
  725.             elseif obj is living
  726.             {
  727.               print CThe(obj); \
  728.                 MatchPlural(obj, "isn't", "aren't"); " here."
  729.             }
  730.             else
  731.             {
  732.               print CThe(player); \
  733.                 MatchPlural(player, "doesn't", "don't"); \
  734.                 " see"; MatchPlural(obj, "that", "those"); \
  735.                 "."
  736.             }
  737.         }
  738.  
  739.         case 12
  740.             print CThe(player); \
  741.               " can't do that with "; The(obj) ; "."
  742.         
  743.         case 14
  744.         {
  745.             if xobject is living
  746.                 print CThe(xobject); \
  747.                   MatchPlural(xobject, "doesn't", "don't"); \
  748.                   " have "; The(obj); "."
  749.             else
  750.                 print CThe(player); \
  751.                   MatchPlural(player, "doesn't", "don't"); \
  752.                   " see "; The(obj); " there."
  753.         }
  754.         
  755.         case 15
  756.         {
  757.             print CThe(player); IsorAre(player); " not
  758.               holding"; MatchPlural(obj, "that", "those"); "."
  759.         }
  760.         
  761.         case else: return false         ! print the default message
  762.  
  763.     return true                             ! message already printed
  764. }
  765.  
  766. routine CustomError(errornumber, obj)   ! to be REPLACED if custom error
  767. {}                                      ! messages are desired for user
  768.                     ! parsing routines
  769.  
  770. !----------------------------------------------------------------------------
  771. ! SpeakTo is called by the engine when a command is addressed to a
  772. ! character object via:  SpeakTo(character)
  773. !
  774. ! For example, the input line
  775. !
  776. !   <character>, get the <object>
  777. !
  778. ! will call SpeakTo(<character>), with the global object containing <object>,
  779. ! and the verbroutine global set to &DoGet
  780.  
  781. #ifclear NO_VERBS
  782.  
  783. routine SpeakTo(char)
  784. {
  785.     speaking = 0
  786.     
  787.     if char is not living
  788.     {
  789.         ParseError(6)
  790.         return
  791.     }
  792.  
  793.     AssignPronoun(char)
  794.  
  795.     if not FindObject(char, location)
  796.     {
  797.         ParseError(11, char)
  798.         return
  799.     }
  800.     elseif char = player
  801.     {
  802.         Message(&Speakto, 1)    ! "Stop talking to yourself..."
  803.         return
  804.     }
  805.  
  806.     if char is unfriendly
  807.         jump IgnorePlayer
  808.  
  809.     speaking = char
  810.  
  811.     select verbroutine
  812.         case 0                  ! Just the character name is given,
  813.                     ! so just "X is listening."
  814.                     !
  815.             Message(&Speakto, 2, char)
  816.  
  817.         case &DoHello           ! Note the ampersands ("&")--or else
  818.         {                       ! the routines themselves would run
  819.                     !
  820.             if not char.order_response
  821.                 Message(&Speakto, 3, char) ! "X nods hello."
  822.         }
  823.         case &DoAskQuestion
  824.             return Perform(&DoAsk, char, object)
  825.         
  826.         case &DoTalk
  827.         {
  828.             if xobject
  829.                 ParseError(6)
  830.             else     
  831.                 return Perform(&DoAsk, char, object)
  832.         }
  833.         case &DoTell
  834.         {
  835.             if object = player
  836.                 return Perform(&DoAsk, char, xobject)
  837.             else
  838.                 jump TryResponse
  839.         }
  840.         case else
  841.         {
  842.  
  843. ! If the character can respond to a request, this should be dealt with by 
  844. ! an order_response property routine; order_response--if it exists--should
  845. ! return false if there is no response for the given verbroutine
  846.  
  847. :TryResponse
  848.             
  849.             if not char.order_response
  850.                 jump IgnorePlayer
  851.             return true
  852.         }
  853.     return false
  854.  
  855. :IgnorePlayer
  856.  
  857.     if not char.ignore_response
  858.         Message(&Speakto, 4, char)      ! "X ignores you."
  859.     speaking = 0
  860.     return true
  861. }
  862.  
  863. #endif  ! ifclear NO_VERBS
  864.  
  865. !----------------------------------------------------------------------------
  866. ! Perform(&action, object, xobject)
  867. ! calls the verbroutine given by <action>, with globals object and xobject
  868. ! as given; returns value returned by <action> (or <object>.before)
  869. !
  870. ! NOTE:  Ensure that the <action> is an address (preceded by &), not a
  871. ! standard routine call.
  872.  
  873. routine Perform(action, obj, xobj)
  874. {
  875.     local r
  876.     local objtemp, xobjtemp, verbtemp
  877.  
  878.     objtemp = object
  879.     xobjtemp = xobject
  880.     verbtemp = verbroutine
  881.     
  882.     object = obj
  883.     xobject = xobj
  884.     verbroutine = action
  885.  
  886.     r = player.before               ! run before routines
  887.     if r:  jump DonePerform
  888.     r = location.before
  889.     if r:  jump DonePerform
  890.     r = xobject.before
  891.     if r:  jump DonePerform
  892.     r = object.before
  893.     if r:  jump DonePerform
  894.  
  895.     r = call action                 ! object.after and xobject.after
  896.                     ! run by verbroutine
  897.     
  898.     run player.after                ! player and location after
  899.     run location.after              ! routines would normally be run
  900.                     ! by the engine
  901.  
  902. :DonePerform
  903.     verbroutine = verbtemp
  904.     object = objtemp
  905.     xobject = xobjtemp
  906.  
  907.     return r
  908. }
  909.  
  910. !----------------------------------------------------------------------------
  911. ! AnyVerb(obj)
  912. ! returns <obj> if the verbroutine global is currently not in the set of
  913. ! xverbs; otherwise returns false
  914.  
  915. routine AnyVerb(obj)
  916. {
  917.     if verbroutine >= &DoHello and verbroutine <= &DoUndo
  918.         return false
  919.     else
  920.         return obj
  921. }
  922.  
  923. !----------------------------------------------------------------------------
  924. ! x = InList(object, property, y)
  925. ! returns false if <y> is not contained in the list of values held in
  926. ! <object>.<property>; otherwise returns the number of the (first) property
  927. ! element equal to <y>
  928.  
  929. routine InList(obj, prop, y)
  930. {
  931.     local i
  932.  
  933.     for (i=1; i<=obj.#prop; i++)
  934.     {
  935.         if obj.prop #i = y:  return i
  936.     }
  937. }
  938.  
  939. !----------------------------------------------------------------------------
  940. ! x = FindObject(object, object location)
  941. ! returns false if <object> is unavailable in <object location>; returns
  942. ! 2 if <object> is visible but not physically accessible
  943.  
  944. routine FindObject(obj, objloc)
  945. {
  946.     local a, p
  947.  
  948.     if obj = nothing or obj = player:  return true
  949.  
  950.     ! The objloc argument is equal to 0 if a) the grammar token is
  951.     ! "anything", or b) the engine is re-testing object availability
  952.     ! given the setting of best_parse_rank during the first pass of
  953.     ! object disambiguation.
  954.     !
  955.     if objloc = 0
  956.     {
  957.         if obj.parse_rank < best_parse_rank
  958.             return false
  959.         else
  960.             best_parse_rank = obj.parse_rank
  961.  
  962.         if not ObjectisKnown(obj)
  963.             return false
  964.         return true
  965.     }
  966.  
  967.     if obj.parse_rank > best_parse_rank
  968.         best_parse_rank = obj.parse_rank
  969.     
  970.     if word[2] = "~all" or word[3] = "~all"
  971.     {
  972.         a = obj.exclude_from_all
  973.         if a < 2
  974.         {
  975.             if a or ExcludeFromAll(obj) = true
  976.                 return false
  977.         }
  978.     }
  979.  
  980. #ifclear NO_FUSES
  981.     if (obj.type = fuse or obj.type = daemon) and obj is not active
  982.         return false
  983. #endif
  984.  
  985.     p = parent(obj)
  986.  
  987.     if obj = objloc or p = objloc or p = player
  988.         {obj is known
  989.         return true}
  990.     elseif (p is not openable or p is platform) and p is not quiet and
  991.         p ~= nothing:
  992.     {
  993.         if FindObject(p, objloc) and ObjectisKnown(p)
  994.             return true
  995.     }
  996.     elseif p is openable and p is open and p is not quiet and
  997.         p ~= nothing:
  998.     {
  999.         if FindObject(p, objloc) and ObjectisKnown(p)
  1000.             return true
  1001.     }
  1002.     elseif (p is openable, not open, transparent, not quiet) and
  1003.         p ~= nothing:
  1004.     {
  1005.         if FindObject(p, objloc) and ObjectisKnown(p)
  1006.             return 2
  1007.     }
  1008.     elseif player not in location and p~= nothing
  1009.     {
  1010.         if Contains(parent(player), obj) and FindObject(p, objloc)
  1011.             return true
  1012.     }
  1013.     
  1014.     if obj.#found_in
  1015.     {
  1016.         for (a=1; a<=obj.#found_in; a++)
  1017.         {
  1018.             if obj.found_in #a and (obj.found_in #a = objloc or
  1019.                 FindObject(obj.found_in #a, objloc)):
  1020.                 {obj is known
  1021.                 return true}
  1022.         }
  1023.     }
  1024.     
  1025.     if obj.#in_scope
  1026.     {
  1027.         for (a=1; a<=obj.#in_scope; a++)
  1028.         {
  1029.             if obj.in_scope #a=objloc or obj.in_scope #a=actor
  1030.                 {obj is known
  1031.                 return true}
  1032.             if obj.in_scope #a and
  1033.                 FindObject(obj.in_scope #a, objloc):
  1034.                 {obj is known
  1035.                 return true}
  1036.         }
  1037.     }
  1038. }       
  1039.  
  1040. routine ObjectisKnown(a)        ! If it is undesirable to use the rules for
  1041. {                               ! disqualifying hitherto unknown objects
  1042.     if a is known           ! from player actions, REPLACE ObjectisKnown
  1043.         return true     ! with a routine that always returns a true
  1044.                 ! value.
  1045. }
  1046.  
  1047. routine ExcludeFromAll(obj)     ! If global decision rules are desired for
  1048. {                               ! "all" actions, REPLACE ExcludeFromAll,
  1049.     return false            ! returning true if <obj> is to be excluded.
  1050. }                               ! Return 2 to force the INCLUSION of <obj>.
  1051.  
  1052. !----------------------------------------------------------------------------
  1053. ! PutInScope(object, actor)
  1054. ! makes <object> accessible to <actor> (where <actor> is usually the player)
  1055. ! provided that <object> has an in_scope property with an empty slot--i.e. 
  1056. ! one that equals 0; returns false if <object> cannot be placed in scope 
  1057. ! of <actor>
  1058. !
  1059. ! RemoveFromScope(object, actor)
  1060. ! removes <object> from the scope of <actor>
  1061.  
  1062. routine PutInScope(obj, act)
  1063. {
  1064.     local a
  1065.     
  1066.     if act = 0:  act = player
  1067.     for (a=1; a<=obj.#in_scope; a++)
  1068.     {
  1069.         if obj.in_scope #a = 0
  1070.             {obj.in_scope #a = act
  1071.             return true}
  1072.     }
  1073. }
  1074.  
  1075. routine RemoveFromScope(obj, act)
  1076. {
  1077.     local a
  1078.  
  1079.     for (a=1; a<=obj.#in_scope; a++)
  1080.     {
  1081.         if obj.in_scope #a = act
  1082.             {obj.in_scope #a = 0
  1083.             return true}
  1084.     }
  1085. }
  1086.  
  1087. !----------------------------------------------------------------------------
  1088. ! AssignPronoun(object)
  1089. ! sets the appropriate pronoun global to <object>
  1090.  
  1091. routine AssignPronoun(obj)
  1092. {
  1093.     if obj = player {return}        
  1094.     
  1095.     if obj is not living
  1096.     {
  1097.         if obj is not plural
  1098.             it_obj = obj
  1099.         else
  1100.             them_obj = obj
  1101.     }
  1102.     else
  1103.     {
  1104.         if obj is plural
  1105.             them_obj = obj
  1106.         elseif obj is female
  1107.             her_obj = obj
  1108.         else
  1109.             him_obj = obj
  1110.     }
  1111. }
  1112.  
  1113. !----------------------------------------------------------------------------
  1114. ! PrintStatusline
  1115. ! prints an appropriate statusline as specified by global STATUSTYPE
  1116.  
  1117. routine PrintStatusline
  1118. {
  1119.     local temp_it_obj
  1120.  
  1121.     temp_it_obj = it_obj
  1122.     Font(BOLD_OFF | ITALIC_OFF | UNDERLINE_OFF | PROP_OFF)
  1123.     color SL_TEXTCOLOR, SL_BGCOLOR
  1124.     window
  1125.     {
  1126.         if not light_source
  1127.             print "In the dark";
  1128.         else
  1129.         {
  1130.             if FORMAT & DESCFORM_F:  print "\_"; 
  1131.             print capital location.name;
  1132.         }
  1133.         
  1134.         if linelength >= 80
  1135.             print to 65;
  1136.         else
  1137.             print to linelength
  1138.  
  1139.         if STATUSTYPE = 1
  1140.             print number score; " / "; number counter;
  1141.         elseif STATUSTYPE = 2
  1142.             print HoursMinutes(counter);
  1143.         print to linelength
  1144.     }
  1145.     color TEXTCOLOR, BGCOLOR
  1146.     Font(DEFAULT_FONT)
  1147.     it_obj = temp_it_obj
  1148. }
  1149.  
  1150. !----------------------------------------------------------------------------
  1151. ! HoursMinutes(val[, military])
  1152. ! prints the time in 12-hour hh:mm format, as given by <val> minutes past
  1153. ! midnight, or in 24-hour hh:mm military-time format if <military> is true
  1154.  
  1155. routine HoursMinutes(val, military)
  1156. {
  1157.     local hours, minutes
  1158.  
  1159.     hours = val / 60
  1160.     minutes = val - hours * 60
  1161.  
  1162.     if not military
  1163.     {
  1164.         if hours > 12:     hours -= 12
  1165.         elseif hours = 0:  hours = 12
  1166.     }
  1167.     elseif hours < 10:  print "0";
  1168.  
  1169.     print number hours; ":";
  1170.     if minutes < 10
  1171.         print "0";
  1172.     print number minutes; " ";
  1173.  
  1174.     if not military
  1175.     {
  1176.         if val > 720
  1177.             print "p.m.";
  1178.         else
  1179.             print "a.m.";
  1180.     }
  1181. }
  1182.  
  1183. !----------------------------------------------------------------------------
  1184. ! The(object)                           ! prints "the <object>"
  1185. !
  1186. ! When the player is in the first person, pass a second, non-false argument
  1187. ! to generate "me" instead of "I".
  1188.  
  1189. routine The(obj, a)
  1190. {
  1191.     AssignPronoun(obj)
  1192.  
  1193.     if obj = player and player_person = 1 and a
  1194.     {
  1195.         print player.pronoun #2;
  1196.         return
  1197.     }
  1198.  
  1199.     if obj.article
  1200.         print "the ";
  1201.     print obj.name;
  1202. }
  1203.  
  1204. !----------------------------------------------------------------------------
  1205. ! CThe(object)                          ! prints "The <object>"
  1206.  
  1207. routine CThe(obj)
  1208. {
  1209.     AssignPronoun(obj)
  1210.  
  1211.     if obj.article
  1212.         print "The "; obj.name;
  1213.     else
  1214.         print capital obj.name;
  1215. }
  1216.  
  1217. !----------------------------------------------------------------------------
  1218. ! Art(object)
  1219.  
  1220. routine Art(obj, a)                     ! prints, for example, "an <object>"
  1221. {
  1222.     AssignPronoun(obj)
  1223.  
  1224.     if obj = player and player_person = 1 and a
  1225.     {
  1226.         print player.pronoun #2;
  1227.         return
  1228.     }
  1229.  
  1230.     if obj.article
  1231.         print obj.article; " ";
  1232.     print obj.name;
  1233. }
  1234.  
  1235. !----------------------------------------------------------------------------
  1236. ! CArt(object)                          ! prints, for example, "An <object>"
  1237.  
  1238. routine CArt(obj)
  1239. {
  1240.     AssignPronoun(obj)
  1241.  
  1242.     if obj.article
  1243.         print capital obj.article; " "; obj.name;
  1244.     else
  1245.         print capital obj.name;
  1246. }
  1247.  
  1248. !----------------------------------------------------------------------------
  1249. ! IsorAre(object, [optional parameter])
  1250. ! prints "is" or "are" (or "'s" or "'re") to agree with <object>
  1251. !
  1252. ! IsorAre(object, true)
  1253. ! forces use of "is" and "are" instead of "'s" and "'re"
  1254.  
  1255. routine IsorAre(obj, a)
  1256. {
  1257.     if obj is plural
  1258.     {
  1259.         if obj = player and player_person = 1
  1260.         {
  1261.             if a:  print " am";
  1262.             else:  print "'m";
  1263.         }
  1264.         else
  1265.         {
  1266.             if a:  print " are";
  1267.             else:  print "'re";
  1268.         }
  1269.     }
  1270.     else
  1271.     {
  1272.         if a:  print " is";
  1273.         else:  print "'s";
  1274.     }
  1275. }
  1276.  
  1277. !----------------------------------------------------------------------------
  1278. ! MatchSubject(object)
  1279. ! conjugates a present-tense verb to agree with <object>
  1280.  
  1281. routine MatchSubject(obj)
  1282. {
  1283.     if obj is not plural
  1284.         print "s";
  1285. }
  1286.  
  1287. !----------------------------------------------------------------------------
  1288. ! MatchPlural(object, word1, word2)
  1289. ! prints <word1> if <object> is singular or <word2> if <object> is plural
  1290.  
  1291. routine MatchPlural(obj, word1, word2)
  1292. {
  1293.     print " ";
  1294.     if obj is not plural
  1295.         print word1;
  1296.     else
  1297.         print word2;
  1298. }
  1299.  
  1300. !----------------------------------------------------------------------------
  1301. ! NumberWord(number)
  1302. ! prints a number in non-numerical word format, where <number> is between
  1303. ! -32767 to 32767
  1304. !
  1305. ! NumberWord(number, true)
  1306. ! prints the word beginning with a capital letter if a second (true)
  1307. ! argument is provided
  1308.  
  1309. routine NumberWord(n, c)
  1310. {
  1311.     local a, f
  1312.  
  1313.     if n = 0
  1314.     {
  1315.         if c:  print capital DigitWord(n);
  1316.         else:  print DigitWord(n);
  1317.         return
  1318.     }
  1319.     if n < 0      
  1320.     {
  1321.         if c:  print "Minus ";
  1322.         else:  print "minus ";
  1323.         n = -n
  1324.         c = 0
  1325.     }
  1326.     
  1327.     f = 1000
  1328.     while n
  1329.     {
  1330.         if n >= f
  1331.         {
  1332.             if a
  1333.             {
  1334.                 if f = 100:     print ", ";
  1335.                 elseif f = 10:  print " "; AND_WORD; " ";
  1336.                 elseif f = 1:   print "-";
  1337.             }
  1338.             
  1339.             if f >= 100
  1340.             {
  1341.                 if c:  NumberWord(n/f, c)
  1342.                 else:  NumberWord(n/f)
  1343.                 print " "; DigitWord(f);
  1344.                 n = n-n/f*f
  1345.             }
  1346.             elseif f = 10 and (n >= 20)
  1347.             {
  1348.                 if c:  print capital DigitWord(n/10*10);
  1349.                 else:  print DigitWord(n/10*10);
  1350.                 n = n-n/f*f
  1351.             }
  1352.             else
  1353.             {
  1354.                 if c:  print capital DigitWord(n);
  1355.                 else:  print DigitWord(n);
  1356.                 n = 0
  1357.             }
  1358.             c = 0
  1359.             a = true
  1360.         }
  1361.         f = f/10
  1362.     }
  1363. }
  1364.  
  1365. routine DigitWord(n)
  1366. {
  1367.     select n
  1368.     case 0:         return "zero"
  1369.     case 1:         return "one"
  1370.     case 2:         return "two"
  1371.     case 3:         return "three"
  1372.     case 4:         return "four"
  1373.     case 5:         return "five"
  1374.     case 6:         return "six"
  1375.     case 7:         return "seven"
  1376.     case 8:         return "eight"
  1377.     case 9:         return "nine"
  1378.     case 10:        return "ten"
  1379.     case 11:        return "eleven"
  1380.     case 12:        return "twelve"
  1381.     case 13:        return "thirteen"
  1382.     case 14:        return "fourteen"
  1383.     case 15:        return "fifteen"
  1384.     case 16:        return "sixteen"
  1385.     case 17:        return "seventeen"
  1386.     case 18:        return "eighteen"
  1387.     case 19:        return "nineteen"
  1388.     case 20:        return "twenty"
  1389.     case 30:        return "thirty"
  1390.     case 40:        return "forty"
  1391.     case 50:        return "fifty"
  1392.     case 60:        return "sixty"
  1393.     case 70:        return "seventy"
  1394.     case 80:        return "eighty"
  1395.     case 90:        return "ninety"
  1396.     case 100:       return "hundred"
  1397.     case 1000:      return "thousand"
  1398. }
  1399.  
  1400. !----------------------------------------------------------------------------
  1401. ! Indent
  1402. ! indents only if the NOINDENT_F bit is not set in the FORMAT mask; returns 
  1403. ! the null word "" (0 or false)
  1404.  
  1405. routine Indent
  1406. {
  1407.     local i
  1408.     
  1409.     if override_indent
  1410.         print AFTER_PERIOD;
  1411.     elseif not (FORMAT & NOINDENT_F) and INDENT_SIZE
  1412.     {
  1413.         print "\_";
  1414.         for (i=2; i<=INDENT_SIZE; i++)
  1415.             print " ";
  1416.     }
  1417.     override_indent = false
  1418. }
  1419.  
  1420. !----------------------------------------------------------------------------
  1421. ! DescribePlace(location, [optional parameter])
  1422. ! prints the location name, followed by the location description, if
  1423. ! required
  1424. !
  1425. ! DescribePlace(location, true)
  1426. ! forces a location description
  1427.  
  1428. routine DescribePlace(place, long)
  1429. {
  1430.     local obj, count, notlisted, tempformat
  1431.  
  1432.     ! Since, for example, a room description following entering via
  1433.     ! DoGo does not trigger before/after properties tied to looking 
  1434.     ! around:
  1435.     !
  1436.     if verbroutine ~= &DoLookAround
  1437.     {
  1438.         if place is not visited and verbosity ~= 1
  1439.             return Perform(&DoLookAround)
  1440.         elseif long = true or verbosity = 2
  1441.             return Perform(&DoLookAround)
  1442.     }
  1443.  
  1444.     if not light_source
  1445.         {Message(&DescribePlace, 1)     ! "It's too dark to see..."
  1446.         return}
  1447.  
  1448.     place is known
  1449.  
  1450.     ! Print the name of the location as a heading
  1451.     Font(BOLD_ON)
  1452.     print "\n"; capital place.name;
  1453.  
  1454.     ! Print ", in <something>" if necessary
  1455.     if location = place and player not in place
  1456.     {
  1457.         if parent(player).prep
  1458.             print ", "; parent(player).prep; " ";
  1459.         else
  1460.             print ", "; IN_WORD; " ";
  1461.         print Art(parent(player))
  1462.     }
  1463.     print newline
  1464.  
  1465.     Font(BOLD_OFF)
  1466.     override_indent = false
  1467.  
  1468.     if place is not visited and verbosity ~= 1
  1469.     {
  1470.         if &place.initial_desc or &place.long_desc
  1471.             Indent
  1472.         if not place.initial_desc
  1473.             run place.long_desc
  1474.     }
  1475.     elseif long = true or verbosity = 2
  1476.     {
  1477.         if &place.long_desc
  1478.             Indent
  1479.         run place.long_desc
  1480.     }
  1481.     
  1482.     if &place.list_contents and FORMAT & DESCFORM_F
  1483.         print ""        ! for double-space-after-heading formatting
  1484.     
  1485.     ! A location may contain an overriding listing routine, as may any
  1486.     ! parent, in the list_contents property
  1487.     !
  1488.     if not place.list_contents
  1489.     {
  1490.         list_nest = 0
  1491.  
  1492.         ! For double-space-after-heading formatting:
  1493.         if FORMAT & DESCFORM_F:
  1494.         {
  1495.             for obj in place
  1496.             {
  1497.                 if obj is not hidden and 
  1498.                   (player not in obj or children(obj) > 1):
  1499.                 {
  1500.                     print ""
  1501.                     break
  1502.                 }
  1503.             }
  1504.         }
  1505.  
  1506.         ! List contents of chair, vehicle, etc. player is in
  1507.         if player not in location
  1508.             WhatsIn(Parent(player))
  1509.             
  1510.         ! List all characters, if any
  1511.         count = 0
  1512.         for obj in place
  1513.         {
  1514.             if obj is hidden or obj is not living or 
  1515.                 player in obj:
  1516.                 obj is already_listed
  1517.             else
  1518.             {
  1519.                 obj is not already_listed
  1520.                 ShortDescribe(obj)
  1521.                 if obj is not already_listed
  1522.                     count++
  1523.             }        
  1524.         }
  1525.         
  1526.         list_count = count
  1527.         count = 0
  1528.  
  1529.         if list_count           ! if characters are to be listed
  1530.         {
  1531.             tempformat = FORMAT
  1532.             FORMAT = FORMAT | FIRSTCAPITAL_F | ISORAREHERE_F
  1533.             FORMAT = FORMAT | USECHARNAMES_F
  1534.             if FORMAT & LIST_F
  1535.             {
  1536.                 FORMAT = FORMAT & ~LIST_F       ! clear it
  1537.                 FORMAT = FORMAT | TEMPLIST_F
  1538.             }
  1539.             Indent
  1540.             list_nest = 0
  1541.             ListObjects(place)
  1542.             FORMAT = tempformat
  1543.         }
  1544.  
  1545.         for obj in place
  1546.         {
  1547. #ifset USE_ATTACHABLES
  1548.             ! Exclude all attachables for now (and characters)
  1549.  
  1550.             if obj is living or obj.type = attachable or
  1551.                 player in obj
  1552. #endif
  1553. #ifclear USE_ATTACHABLES
  1554.             if obj is living or player in obj
  1555. #endif
  1556.                 obj is already_listed
  1557.             else
  1558.                 obj is not already_listed
  1559.         }
  1560.         
  1561.         for obj in place
  1562.         {
  1563. #ifset USE_PLURAL_OBJECTS
  1564.             ! ...And don't list identical objects yet, either
  1565.  
  1566.             if (obj.identical_to).type = identical_class
  1567.             {
  1568.                 if obj is not hidden
  1569.                     count++
  1570.             }
  1571.             elseif player not in obj
  1572. #endif
  1573. #ifclear USE_PLURAL_OBJECTS
  1574.             if player not in obj
  1575. #endif
  1576.             {
  1577.                 if obj is not already_listed and
  1578.                     obj is not hidden:
  1579.                 {
  1580.                     ShortDescribe(obj)
  1581.                     if obj is not already_listed
  1582.                         notlisted++
  1583.                 }
  1584.             }
  1585.         }
  1586.  
  1587.         if notlisted or count
  1588.         {
  1589.             list_count = notlisted + count
  1590.             tempformat = FORMAT
  1591.             FORMAT = FORMAT | FIRSTCAPITAL_F | ISORAREHERE_F
  1592.             if FORMAT & LIST_F
  1593.             {
  1594.                 FORMAT = FORMAT & ~LIST_F       ! clear it
  1595.                 FORMAT = FORMAT | TEMPLIST_F
  1596.             }
  1597.             Indent
  1598.             list_nest = 0
  1599.             ListObjects(place)
  1600.             FORMAT = tempformat
  1601.         }
  1602.  
  1603. #ifclear NO_OBJLIB
  1604. #ifset USE_ATTACHABLES
  1605.         for obj in place
  1606.         {
  1607.             ! Print attachables last
  1608.             if obj.type = attachable and obj is not hidden
  1609.             {
  1610.                 ShortDescribe(obj)
  1611.                 if obj is not already_listed
  1612.                     Message(&DescribePlace, obj, 2)
  1613.             }
  1614.         }
  1615. #endif
  1616.  
  1617.         print newline
  1618.         override_indent = false
  1619.         
  1620.         ! Finally, list contents of scenery objects
  1621.         for obj in place
  1622.         {
  1623.             if obj.type = scenery
  1624.                 WhatsIn(obj)
  1625.         }
  1626. #endif  ! ifclear NO_OBJLIB
  1627.     
  1628.     }
  1629. }
  1630.  
  1631. !----------------------------------------------------------------------------
  1632. ! ShortDescribe(object)
  1633. ! prints the initial description of <object> if not moved (if it has one),
  1634. ! or the when_open or when_closed message, if applicable, or the short 
  1635. ! description if moved (if it has one).
  1636.  
  1637. routine ShortDescribe(obj)
  1638. {
  1639.     obj is known
  1640.     
  1641.     AssignPronoun(obj)
  1642.  
  1643.     if obj is not moved and &obj.initial_desc 
  1644.     {
  1645.         Indent
  1646.         run obj.initial_desc
  1647.         jump CheckContents
  1648.     }
  1649.             
  1650.     if obj is openable
  1651.     {
  1652.         if obj is open 
  1653.         {
  1654.             if &obj.when_open 
  1655.             {
  1656.                 Indent
  1657.                 run obj.when_open
  1658.                 jump CheckContents
  1659.             }
  1660.         }
  1661.         elseif &obj.when_closed 
  1662.         {
  1663.             Indent
  1664.             run obj.when_closed
  1665.             jump CheckContents
  1666.         }
  1667.     }
  1668.             
  1669.     if &obj.short_desc 
  1670.         Indent
  1671.     
  1672.     if not obj.short_desc
  1673.         return
  1674.  
  1675. :CheckContents
  1676.  
  1677.     obj is already_listed
  1678.     AssignPronoun(obj)
  1679.  
  1680.     list_count = 0
  1681.     if children(obj) > 0 and (obj is not container or
  1682.         (obj is container and obj is not openable) or
  1683.         (obj is container and obj is openable and 
  1684.             (obj is open or obj is transparent))) and
  1685.         obj is not quiet:
  1686.     {
  1687.         list_nest = 1
  1688.         WhatsIn(obj)
  1689.     }
  1690.     if need_newline:  print newline
  1691. }
  1692.  
  1693. !----------------------------------------------------------------------------
  1694. ! WhatsIn(object)
  1695. ! lists the children of <object>, if any, in a relatively orderly manner
  1696.  
  1697. routine WhatsIn(obj)
  1698. {
  1699.     local i, totallisted
  1700.     
  1701.     if FORMAT & NORECURSE_F
  1702.         return
  1703.  
  1704.     for i in obj
  1705.     {
  1706.         i is not already_listed
  1707.         if i is not hidden
  1708.             totallisted++
  1709.     }
  1710.  
  1711.     if totallisted = 0
  1712.         return
  1713.  
  1714.     list_count = totallisted
  1715.     SpecialDesc(obj)
  1716.     
  1717. ! If list_count is 0 now, but totallisted was not, something must have been 
  1718. ! printed by SpecialDesc
  1719.  
  1720.     if list_count = 0
  1721.     {
  1722.         if FORMAT&INVENTORY_F and not (FORMAT&LIST_F) and 
  1723.             list_nest = 0:
  1724.             print ""
  1725.         return totallisted
  1726.     }
  1727.  
  1728.     if obj is not container or
  1729.         (obj is container and (obj is not openable or
  1730.             (obj is openable and 
  1731.                 (obj is open or obj is transparent)))) and
  1732.         (obj ~= player or FORMAT & INVENTORY_F) and obj is not quiet:
  1733.     {
  1734.         if obj.list_contents
  1735.             return totallisted
  1736.  
  1737.         if FORMAT & LIST_F
  1738.             print to (list_nest * INDENT_SIZE);
  1739.         else
  1740.             Indent                
  1741.  
  1742.         if obj.contains_desc    ! custom heading
  1743.         {
  1744.             if FORMAT & LIST_F
  1745.                 print ":"
  1746.         }
  1747.         else
  1748.         {
  1749.             if obj = player
  1750.             {
  1751.                 if FORMAT & LIST_F and list_count<totallisted
  1752.                     print "\n";
  1753.                 
  1754.                 ! "You are carrying..."
  1755.                 Message(&WhatsIn, 1, totallisted)
  1756.                 
  1757.                 if FORMAT & LIST_F
  1758.                     print ":"
  1759.             }
  1760.             elseif obj is living and not obj.prep
  1761.             {
  1762.                 ! "X has..."
  1763.                 Message(&WhatsIn, 2, obj, totallisted)
  1764.                 if FORMAT & LIST_F
  1765.                     print ":"
  1766.             }
  1767.             else
  1768.             {
  1769.                 if list_count < totallisted
  1770.  
  1771.                     ! "Also sitting on/in..."
  1772.                     Message(&Whatsin, 3, obj)
  1773.                 else
  1774.  
  1775.                     ! "Sitting on/in..."
  1776.                     Message(&Whatsin, 4, obj)
  1777.                 
  1778.                 The(obj)
  1779.                 FORMAT = FORMAT | ISORARE_F
  1780.             }
  1781.         }
  1782.         ListObjects(obj)
  1783.     }
  1784.     return totallisted
  1785. }
  1786.  
  1787. !----------------------------------------------------------------------------
  1788. ! SpecialDesc(object)        
  1789. ! checks the children of <object> and runs any applicable preliminary
  1790. ! descriptions; returns the total number of remaining (i.e. non-listed) 
  1791. ! objects in the list_count global variable
  1792.  
  1793. routine SpecialDesc(obj) 
  1794. {
  1795.     local a, c
  1796.                
  1797.     if FORMAT & LIST_F
  1798.         return
  1799.     
  1800.     list_count = 0
  1801.     for a in obj
  1802.     {
  1803.         if a is not hidden:  c++
  1804.         
  1805.         if FORMAT & INVENTORY_F and obj = player 
  1806.         {
  1807.             if &a.inv_desc 
  1808.                 Indent
  1809.             if a.inv_desc
  1810.             {
  1811.                 if FORMAT & LIST_F:  print newline
  1812.                 else:  print AFTER_PERIOD;
  1813.                 AddSpecialDesc(a)
  1814.             }
  1815.         }
  1816.         
  1817.         elseif a is not moved
  1818.         {
  1819.             if &a.initial_desc 
  1820.             {
  1821.               print newline
  1822.               override_indent = false
  1823.               if FORMAT & INVENTORY_F and FORMAT & NOINDENT_F
  1824.                 print ""
  1825.               Indent
  1826.             }
  1827.             if a.initial_desc
  1828.                 AddSpecialDesc(a)
  1829.         }
  1830.     }
  1831.     list_count = c - list_count
  1832. }
  1833.  
  1834. routine AddSpecialDesc(a)
  1835. {
  1836.     a is already_listed
  1837.     a is known
  1838.     list_count++
  1839.     AssignPronoun(a)
  1840. }
  1841.  
  1842. !----------------------------------------------------------------------------
  1843. ! ListObjects(object)          
  1844. ! lists all the objects in <object>, providing that the list_count global 
  1845. ! contains the total number of objects to be listed.  
  1846.  
  1847. routine ListObjects(thisobj)
  1848. {
  1849.     local k, obj, count, pluralcount
  1850.     local templist_count            ! temporary total of unlisted objs.
  1851.     local id_count                  ! for identical (or plural) objects
  1852. #ifset USE_PLURAL_OBJECTS
  1853.     local i, j, this_class
  1854. #endif
  1855.     
  1856.     list_nest++
  1857.     for obj in thisobj
  1858.     {
  1859.         if obj is hidden
  1860.         {
  1861.             obj is already_listed
  1862.             if obj.type = scenery
  1863.                 obj is known
  1864.         }
  1865.         else
  1866.             obj is known
  1867.  
  1868. #ifset USE_PLURAL_OBJECTS
  1869.  
  1870.         ! Need to count identical (and possibly plural) objects
  1871.         ! for grouping in listing
  1872.  
  1873.         if obj.identical_to and obj is not already_listed
  1874.         {
  1875.             this_class = obj.identical_to
  1876.             if this_class.type = identical_class or
  1877.                 FORMAT & GROUPPLURALS_F:
  1878.             {
  1879.               id_count = 1
  1880.               for (i=1; i<=this_class.#plural_of; i++)
  1881.               {
  1882.                 j = this_class.plural_of #i
  1883.                 if j in thisobj and j~=obj and j is not hidden
  1884.                   {id_count++
  1885.                   pluralcount++
  1886.                   list_count--
  1887.                   j is already_listed}
  1888.               }
  1889.             }
  1890.         }
  1891. #endif
  1892.         if obj is not already_listed
  1893.         {
  1894.             ! May have a leading "is" or "are" that needs to
  1895.             ! be printed at the head of the list
  1896.             
  1897.             if FORMAT & ISORARE_F
  1898.             {
  1899.                 if list_count = 1 and id_count <= 1 and
  1900.                     obj is not plural:
  1901.                     print " "; IS_WORD;
  1902.                 else:  print " "; ARE_WORD;
  1903.                 if FORMAT & LIST_F
  1904.                     print ":"
  1905.                 FORMAT = FORMAT & ~ISORARE_F    ! clear it
  1906.             }
  1907.             
  1908.             need_newline = false
  1909.             if obj is plural
  1910.                 pluralcount++
  1911.  
  1912.             AssignPronoun(obj)
  1913.             if not (FORMAT & LIST_F)
  1914.             {       
  1915.               if list_count > 2 and count
  1916.                 print ",";
  1917.               if list_count > 1 and count = list_count - 1 
  1918.                 print " "; AND_WORD;
  1919.               if not (FORMAT & FIRSTCAPITAL_F)
  1920.                 print " ";
  1921.             }
  1922.             else
  1923.             {
  1924.                 print to (list_nest * INDENT_SIZE);
  1925.             }
  1926.  
  1927. #ifset USE_PLURAL_OBJECTS
  1928.             
  1929.             ! If a number of identical (or possibly plural)
  1930.             ! objects are grouped together, they are printed
  1931.             ! as a single entry in the list
  1932.             !
  1933.             if obj.identical_to and
  1934.                 (this_class.type = identical_class or
  1935.                 FORMAT & GROUPPLURALS_F):
  1936.             {
  1937.               if id_count = 1
  1938.               {
  1939.                 if FORMAT & FIRSTCAPITAL_F
  1940.                   CArt(obj)
  1941.                 else
  1942.                   Art(obj)
  1943.               }
  1944.               else
  1945.               {
  1946.                 if FORMAT & FIRSTCAPITAL_F
  1947.                   print NumberWord(id_count, true);
  1948.                 else
  1949.                   print NumberWord(id_count); 
  1950.                 print " "; this_class.name;
  1951.               
  1952.                 if this_class.type = plural_class
  1953.                 {
  1954.                   if FORMAT & LIST_F
  1955.                 print ":";
  1956.                   else
  1957.                 print " (";
  1958.  
  1959.                   k = 0
  1960.                   for (i=1; i<=this_class.#plural_of; i++)
  1961.                   {
  1962.                 j = this_class.plural_of #i
  1963.                 if parent(j) = thisobj
  1964.                 {
  1965.                   if not (FORMAT & LIST_F)
  1966.                   {
  1967.                     if id_count > 2 and k:  print ",";
  1968.                     if k = id_count - 1:  print " "; AND_WORD;
  1969.                     if k:  print " ";
  1970.                   }
  1971.                   else
  1972.                   {
  1973.                     print "\n"; 
  1974.                     print to ((list_nest+1) * INDENT_SIZE);
  1975.                   }
  1976.                   Art(j)
  1977.                   ObjectIs(j)
  1978.                   k++
  1979.                 }
  1980.                   }
  1981.                   if not (FORMAT & LIST_F):  print ")";
  1982.                 }
  1983.               }
  1984.             }
  1985.             else
  1986.             {
  1987. #endif
  1988.                 ! Regular old non-plural, non-identical
  1989.                 ! objects get listed here:
  1990.  
  1991.                 if FORMAT & FIRSTCAPITAL_F
  1992.                     CArt(obj)
  1993.                 else:  Art(obj)
  1994.                 ObjectIs(obj)
  1995. #ifset USE_PLURAL_OBJECTS
  1996.             }
  1997. #endif
  1998.             FORMAT = FORMAT & ~FIRSTCAPITAL_F       ! clear it
  1999.             
  2000.             ! For itemized listings, list the children of
  2001.             ! each object immediately after that object (unless
  2002.             ! it is a SpecialDesc-printed description)
  2003.  
  2004.             if FORMAT & LIST_F
  2005.             {
  2006.                 print newline
  2007.                 if children(obj)
  2008.                 {
  2009.                     if not obj.list_contents
  2010.                     {
  2011.                       templist_count = list_count
  2012.                       WhatsIn(obj)
  2013.                       list_count = templist_count
  2014.                     }
  2015.                 }
  2016.             }
  2017.             count++
  2018.         }
  2019.     }
  2020.     
  2021.     ! If not an itemized list, it is necessary to finish off the 
  2022.     ! sentence, adding any necessary words at the end.  Then, the
  2023.     ! children of all previously objects listed at this level are
  2024.     ! listed.
  2025.     
  2026.     if not (FORMAT & LIST_F)
  2027.     {
  2028.         if count 
  2029.         {
  2030.             if list_nest = 1 and FORMAT & ISORAREHERE_F
  2031.             {
  2032.                 if count + pluralcount > 1
  2033.                     print " "; ARE_WORD;
  2034.                 else:  print " "; IS_WORD;
  2035.                 print " "; HERE_WORD;
  2036.                 FORMAT = FORMAT & ~ISORAREHERE_F  ! clear it
  2037.                 
  2038.                 if not (FORMAT&LIST_F or FORMAT&TEMPLIST_F)
  2039.                     override_indent = true
  2040.             }
  2041.             print ".";
  2042.             
  2043.             if FORMAT & NOINDENT_F  ! force spacing if needed
  2044.                 k = 1
  2045.             else:  k = 0
  2046.         }
  2047.  
  2048.         for obj in thisobj
  2049.         {
  2050.             if children(obj) and obj is not hidden and
  2051.                 (obj is not already_listed or 
  2052.                     thisobj ~= location):
  2053.             {        
  2054.                 if FORMAT & TEMPLIST_F
  2055.                 {
  2056.                     FORMAT = FORMAT | LIST_F & ~TEMPLIST_F 
  2057.                     print newline
  2058.                 }
  2059.                 elseif k            ! print forced spacing
  2060.                 {
  2061.                     print AFTER_PERIOD;
  2062.                     k = 0
  2063.                 }
  2064.                 
  2065.                 templist_count = list_count
  2066.                 WhatsIn(obj)
  2067.                 list_count = templist_count
  2068.             }
  2069.         }
  2070.  
  2071.         if count and k:  print AFTER_PERIOD;
  2072.     }
  2073.  
  2074.     if --list_nest = 0
  2075.     {
  2076.         if not (FORMAT & LIST_F)
  2077.         {
  2078.             print newline
  2079.             override_indent = false
  2080.             need_newline = false
  2081.         }
  2082.     }
  2083. }
  2084.  
  2085. !----------------------------------------------------------------------------
  2086. ! PropertyList(object, property[, article])
  2087. ! lists all the objects in <object>.<property>, returning the number of
  2088. ! objects printed; if <article> is false or omitted, the indefinite article
  2089. ! is used
  2090.  
  2091. routine PropertyList(obj, prop, artic)
  2092. {
  2093.     local a, b, n, total
  2094.  
  2095.     for (a=1; a<=obj.#prop; a++)
  2096.     {
  2097.         if obj.prop #a:  total++
  2098.     }
  2099.     
  2100.     for (a=1; a<=obj.#prop; a++)
  2101.     {
  2102.         b = obj.prop #a
  2103.         if b
  2104.         {
  2105.             if artic
  2106.                 The(b)
  2107.             else
  2108.                 Art(b)
  2109.             
  2110.             if a < total and total > 2
  2111.                 print ", ";
  2112.             elseif a = total - 1:  print " ";
  2113.  
  2114.             if a = total - 1
  2115.                 print AND_WORD; " ";
  2116.             n++
  2117.         }
  2118.     }
  2119.     return n
  2120. }
  2121.  
  2122. !----------------------------------------------------------------------------
  2123. ! MovePlayer(location[, silent])
  2124. ! moves the player to the object <location>, with no description if <silent>
  2125. ! is true
  2126. !
  2127. ! MovePlayer(direction[, silent[, ignore]])
  2128. ! moves player in <direction>, where <direction> is a direction object.
  2129. ! If <ignore> is true, before/after routines relating to the move are
  2130. ! not checked.
  2131. !
  2132. ! MovePlayer calls DarkWarning when there is no light source in the new
  2133. ! location; REPLACE it with a new DarkWarning routine for a more elaborate
  2134. ! response, such as the possible demise of the player
  2135.  
  2136. routine MovePlayer(loc, silent, ignore)
  2137. {
  2138.     local l, v, obj, xobj, ret
  2139.     
  2140. #ifclear NO_OBJLIB
  2141.     if loc.type = direction
  2142.     {
  2143.         l = location.(loc.dir_to)
  2144.         if l > 1                ! since a message always returns 1
  2145.             loc = location.(loc.dir_to)
  2146.         else
  2147.             return
  2148.     }
  2149. #endif
  2150.  
  2151. #ifset USE_ATTACHABLES
  2152.     if ObjectisAttached(player, location, loc)
  2153.         return
  2154. #endif
  2155.  
  2156.     ! Check if there's a before routine for MovePlayer in the new
  2157.     ! location.  Note that the (potential) new location and the old
  2158.     ! location are stored in object and xobject, respectively.
  2159.     !
  2160.     v = verbroutine
  2161.     obj = object
  2162.     xobj = xobject
  2163.     verbroutine = &MovePlayer
  2164.     object = loc
  2165.     xobject = location
  2166.     if not ignore
  2167.     {
  2168.         ret = location.before
  2169.         if ret:  jump LeaveMovePlayer
  2170.     }
  2171.     
  2172.     move player to loc
  2173.     old_location = location
  2174.     if parent(loc) = 0              ! if it's likely a room object
  2175.         location = loc
  2176.     else                            ! if it's an enterable object
  2177.         location = parent(loc)  ! (noting that the object must be
  2178.                     ! in a room, not inside another
  2179.                     ! non-room object)
  2180.  
  2181. #ifset USE_ATTACHABLES
  2182.     MoveAllAttachables(player, old_location, location)
  2183. #endif
  2184.     
  2185.     PrintStatusline
  2186.  
  2187. :LeaveMovePlayer
  2188.  
  2189.     if not ret
  2190.     {
  2191.         if not FindLight(location)
  2192.             DarkWarning
  2193.         elseif not silent
  2194.             {DescribePlace(location)
  2195.             location is visited}
  2196.  
  2197.     ! Check if there's an after routine for MovePlayer in the new
  2198.     ! location:
  2199.     !
  2200.         if not ignore
  2201.             ret = location.after
  2202.     }
  2203.  
  2204.     verbroutine = v
  2205.     object = obj
  2206.     xobject = xobj
  2207.  
  2208.     return ret
  2209. }
  2210.  
  2211. routine DarkWarning
  2212. {
  2213.     print CThe(player); " stumble"; MatchSubject(player); \
  2214.         " around in the dark."
  2215. }
  2216.  
  2217. !----------------------------------------------------------------------------
  2218. ! x = FindLight(object)
  2219. ! returns the object number of light_source if any light is visible from 
  2220. ! within <object> (where <object> is usually a location)
  2221. !
  2222. ! ObjectisLight is called by FindLight
  2223.  
  2224. routine FindLight(loc)
  2225. {
  2226.     light_source = 0
  2227.  
  2228.     if loc is light
  2229.         {light_source = loc
  2230.         return light_source}
  2231.     elseif ObjectisLight(player)
  2232.         return light_source
  2233.     return ObjectisLight(loc)
  2234. }
  2235.  
  2236. routine ObjectisLight(obj)
  2237. {
  2238.     local nextobj
  2239.  
  2240.     if obj is light
  2241.         {light_source = obj
  2242.         return light_source}
  2243.     if obj is not container or
  2244.         (obj is container and obj is not openable) or 
  2245.         (obj is container and obj is openable and
  2246.             (obj is open or obj is transparent)):
  2247.     {
  2248.         for nextobj in obj
  2249.         {
  2250.             if ObjectisLight(nextobj)
  2251.                 return light_source
  2252.         }
  2253.     }
  2254. }
  2255.  
  2256. !----------------------------------------------------------------------------
  2257. ! ObjectIs(object)
  2258. ! prints a list of parenthetical attributes
  2259.  
  2260. routine ObjectIs(obj)
  2261. {
  2262.     local n
  2263.     
  2264.     if obj is clothing:  n = TestObjectIs(obj, worn, "being worn", n)
  2265.     n = TestObjectIs(obj, light, "providing light", n)
  2266.  
  2267.     if n:  print ")";
  2268.     
  2269.     run obj.desc_detail
  2270. }
  2271.  
  2272. routine TestObjectIs(obj, attr, str, n)
  2273. {
  2274.     if obj is attr
  2275.     {
  2276.         if n = 0
  2277.             print " (";
  2278.         else
  2279.             print " "; AND_WORD;
  2280.         print str;
  2281.         n++
  2282.     }
  2283.     return n
  2284. }
  2285.  
  2286. !----------------------------------------------------------------------------
  2287. ! x = Acquire(object 1, object 2)
  2288. ! moves <object 2> to <object 1>; returns true if successful
  2289.  
  2290. routine Acquire(newparent, newchild)
  2291. {
  2292.     local p
  2293.     
  2294.     CalculateHolding(newparent)
  2295.     
  2296.     if newparent.holding + newchild.size > newparent.capacity
  2297.         return false
  2298.     else
  2299.     {
  2300.         p = parent(newchild)
  2301.         CalculateHolding(p)
  2302.         p.holding = p.holding - newchild.size
  2303.         move newchild to newparent
  2304.         newchild is moved
  2305.         newchild is not hidden
  2306.         newparent.holding = newparent.holding + newchild.size
  2307.         return true
  2308.     }
  2309. }
  2310.  
  2311. !----------------------------------------------------------------------------
  2312. ! CalculateHolding(object)
  2313. ! recalculates the correct holding property for an object; used before 
  2314. ! adding or subtracting children
  2315.  
  2316. routine CalculateHolding(obj)
  2317. {
  2318.     local i
  2319.  
  2320.     obj.holding = 0
  2321.     for i in obj
  2322.         obj.holding = obj.holding + i.size
  2323. }
  2324.  
  2325. !----------------------------------------------------------------------------
  2326. ! x = Contains(object 1, object 2)
  2327. ! returns <object2> if <object 1> contains <object 2> (even as a grandchild)
  2328.  
  2329. routine Contains(obj, possible_child)
  2330. {
  2331.     local nextobj
  2332.  
  2333.     for (nextobj=parent(possible_child); nextobj; nextobj=parent(nextobj))
  2334.     {
  2335.         if nextobj = obj
  2336.             return possible_child
  2337.     }
  2338. }
  2339.  
  2340. !----------------------------------------------------------------------------
  2341. ! x = CheckReach(object)
  2342. ! returns true if either player object's current parent has no reach
  2343. ! property specified, or if <object> is in the list of reachable objects
  2344.  
  2345. routine CheckReach(obj)
  2346. {
  2347.     local i
  2348.  
  2349.     if not parent(player).reach or Contains(parent(player), obj)
  2350.         return true
  2351.  
  2352.     if parent(obj) is living
  2353.     {
  2354.         if verbroutine ~= &DoGet, &DoLook
  2355.             
  2356.             ! "Except that X has it..."
  2357.             Message(&CheckReach, 1, obj)
  2358.  
  2359.         elseif verbroutine = &DoGet and parent(obj) is unfriendly
  2360.             
  2361.             ! "Except that X doesn't want to give it to you..."
  2362.             Message(&CheckReach, 2, obj)
  2363.     }
  2364.     
  2365.     for (i=1; i<=parent(player).#reach; i++)
  2366.     {
  2367.         if Contains(parent(player).reach #i, obj) or
  2368.             obj = parent(player).reach #i:
  2369.             return true
  2370.     }
  2371.  
  2372.     ! "You can't reach it..."
  2373.     Message(&CheckReach, 3, obj)
  2374. }
  2375.  
  2376. !----------------------------------------------------------------------------
  2377. ! GetInput
  2378. ! receives input from the keyboard, parsing into the word[] array; unknown
  2379. ! words--i.e. those that aren't in the dictionary--are equated to the null
  2380. ! string ("")
  2381. !
  2382. ! GetInput(prompt)
  2383. ! where the optional <prompt> represents a dictionary word, prints <prompt> 
  2384. ! before receiving input
  2385.  
  2386. routine GetInput(p)
  2387. {
  2388.     local temp
  2389.  
  2390.     temp = prompt
  2391.     prompt = p
  2392.     input
  2393.     prompt = temp
  2394. }
  2395.  
  2396. !----------------------------------------------------------------------------
  2397. ! x = YesorNo
  2398. ! returns true if word[1] is "yes", false if "no"; prompts for a
  2399. ! new input if neither
  2400.  
  2401. routine YesorNo
  2402. {
  2403.     local w
  2404.     w = word[1]
  2405.     while true
  2406.     {
  2407.         if w = "yes", "y"
  2408.             return true
  2409.         elseif w = "no", "n"
  2410.             return false
  2411.  
  2412.         Message(&YesorNo)       ! ask "yes" or "no"
  2413.         GetInput
  2414.         w = word[1]
  2415.     }
  2416. }
  2417.  
  2418. !----------------------------------------------------------------------------
  2419. ! Font(style mask)
  2420. ! changes the font style based on the style(s) specified in <style mask>,
  2421. ! which may consist of one or more font bitmask constants combined with
  2422. ! the "+" or "|" operator:
  2423. !
  2424. !       Font(BOLD_ON | ITALIC_OFF | ...)
  2425.  
  2426. #ifclear NO_FONTS
  2427. routine Font(mask)
  2428. {
  2429.     if mask & BOLD_ON:        print "\B";
  2430.     if mask & BOLD_OFF:       print "\b";
  2431.     if mask & ITALIC_ON:      print "\I";
  2432.     if mask & ITALIC_OFF:     print "\i";
  2433.     if mask & UNDERLINE_ON:   print "\U";
  2434.     if mask & UNDERLINE_OFF:  print "\u";
  2435.     if mask & PROP_ON:        print "\P";
  2436.     if mask & PROP_OFF:       print "\p";
  2437. }
  2438. #endif
  2439.  
  2440.  
  2441. !----------------------------------------------------------------------------
  2442. ! AUXILIARY MATH ROUTINES:
  2443. !
  2444. ! Function:     Returns:
  2445. !
  2446. ! higher(a, b)  the greater of <a> or <b>
  2447. ! lower(a, b)   the lower of <a> or <b>
  2448. ! mod(a, b)     the remainder of <a> divided by <b>
  2449. ! pow(a, b)     <a> to the power of <b>
  2450.  
  2451. #ifclear NO_AUX_MATH
  2452.  
  2453. routine higher(a, b)
  2454. {
  2455.     if a > b:  return a
  2456.     return b
  2457. }
  2458.  
  2459. routine lower(a, b)
  2460. {
  2461.     if a < b:  return a
  2462.     return b
  2463. }
  2464.  
  2465. routine mod(a, b)
  2466.     {return a-(a/b*b)}
  2467.  
  2468. routine pow(a, b)
  2469. {
  2470.     local i, n
  2471.  
  2472.     if b = 0:  return 1
  2473.     if b < 0:  return 0
  2474.     n = a
  2475.     for (i=2; i<=b; i++)
  2476.         n = n * a
  2477.     return n
  2478. }
  2479.  
  2480. #endif  ! ifclear NO_AUX_MATH
  2481.  
  2482. !----------------------------------------------------------------------------
  2483. ! STRING ARRAY ROUTINES:
  2484. !
  2485. ! StringCompare(array1, array2)
  2486. ! returns 1 if <array1> is lexically greater than <array2>, -1 if <array1>
  2487. ! is lexically less than <array2>, and 0 if the two string arrays are
  2488. ! identical
  2489. !
  2490. ! StringCopy(new, old)
  2491. ! StringCopy(new, old, length)
  2492. ! either copies the array beginning at <old> to <new>, to a maximum of
  2493. ! <length> characters, if specified
  2494. !
  2495. ! StringDictCompare(array, dictentry)
  2496. ! for comparing a string array with a dictionary entry; return values are
  2497. ! as for StringCompare
  2498. !
  2499. ! StringEqual(array1, array2)
  2500. ! returns true if the two strings are identical
  2501. !
  2502. ! x = StringLength(array)
  2503. ! returns the number of characters in string <array>
  2504. !
  2505. ! StringPrint(array)
  2506. ! StringPrint(array, start, end)
  2507. ! either prints the string stored in <array>, beginning and ending with
  2508. ! <start> and <end>, if specified
  2509.  
  2510. #ifclear NO_STRING_ARRAYS
  2511.  
  2512. #ifclear _TEMP_STRING_DEFINED
  2513. array _temp_string[256]                 ! maximum string length is 255 char.
  2514. #set _TEMP_STRING_DEFINED
  2515. #endif
  2516.  
  2517. routine StringCompare(a, b)
  2518. {
  2519.     local i, alen
  2520.  
  2521.     alen = StringLength(a)
  2522.  
  2523.     for (i=0; i<alen; i++)
  2524.     {
  2525.         if array a[i] > array b[i]:     return  1
  2526.         elseif array a[i] < array b[i]: return -1
  2527.     }
  2528.     if array b[i] ~= 0:  return -1
  2529. }
  2530.  
  2531. routine StringCopy(new, old, len)
  2532. {
  2533.     local i
  2534.     
  2535.     if len = 0
  2536.         len = StringLength(old)
  2537.  
  2538.     for (i=0; i<len; i++)
  2539.         array new[i] = array old[i]
  2540.     array new[len] = 0
  2541. }
  2542.  
  2543. routine StringDictCompare(a, d)
  2544. {
  2545.     string(_temp_string, d, 255)
  2546.     return StringCompare(a, _temp_string)
  2547. }
  2548.  
  2549. routine StringEqual(a, b)
  2550.     {return not StringCompare(a, b)}
  2551.  
  2552. routine StringLength(arr)
  2553. {
  2554.     local i
  2555.     i = 0
  2556.     while array arr[i] ~= 0:  i++
  2557.     return i
  2558. }
  2559.  
  2560. routine StringPrint(a, start, end)
  2561. {
  2562.     local i
  2563.  
  2564.     if end = 0
  2565.         end = StringLength(a)
  2566.     for (i=start; i<end; i++)
  2567.     {
  2568.         if array a[i] = 0
  2569.             break
  2570.         printchar array a[i]
  2571.     }
  2572. }
  2573.  
  2574. #endif  ! ifclear NO_STRING_ARRAYS
  2575.  
  2576. !----------------------------------------------------------------------------
  2577. ! x = Menu(number, [width])
  2578. ! The Menu routine expects the array menuitem[] to hold a series of
  2579. ! dictionary entries representing the list of possible choices, with the 
  2580. ! title of the menu contained in menuitem[0].  It returns the number chosen, 
  2581. ! or 0 if none is selected.
  2582. !
  2583. ! The argument <number> gives the number of menu items, and the optional 
  2584. ! <width> gives the width of the menu, in characters.  If no width is 
  2585. ! specified, it defaults to the greater of 20 or the longest menu choice.
  2586.  
  2587. #ifclear NO_MENUS
  2588.  
  2589. #ifclear _TEMP_STRING_DEFINED
  2590. array _temp_string[256]
  2591. #set _TEMP_STRING_DEFINED
  2592. #endif
  2593.  
  2594. array menuitem[11]                      ! up to 10 items (plus title)
  2595. global MENU_TEXTCOLOR
  2596. global MENU_BGCOLOR
  2597. global MENU_SELECTCOLOR
  2598. global MENU_SELECTBGCOLOR
  2599.  
  2600. routine Menu(num, width)
  2601. {
  2602.     local a, i, column, olda
  2603.     
  2604.     Font(BOLD_OFF | ITALIC_OFF | UNDERLINE_OFF | PROP_OFF)
  2605.     
  2606.     if MENU_TEXTCOLOR=0 and MENU_BGCOLOR=0  ! must not have been set
  2607.         {MENU_TEXTCOLOR = TEXTCOLOR
  2608.         MENU_BGCOLOR = BGCOLOR
  2609.         MENU_SELECTCOLOR = SL_TEXTCOLOR
  2610.         MENU_SELECTBGCOLOR = SL_BGCOLOR}
  2611.  
  2612.     if width = 0:  width = 20
  2613.     for (i=1; i<=num; i++)          ! determine appropriate width
  2614. #ifclear NO_AUX_MATH
  2615.         width = higher(width, string(_temp_string, menuitem[i]))
  2616. #endif
  2617. #ifset NO_AUX_MATH
  2618.         {a = string(_temp_string, menuitem[i])
  2619.         if a > width:  width = a}
  2620. #endif
  2621.  
  2622.     column = linelength/2 - width/2
  2623.  
  2624.     CenterTitle(menuitem[0])        ! print title of menu
  2625.  
  2626.     color MENU_TEXTCOLOR, MENU_BGCOLOR
  2627.     Font(BOLD_OFF | ITALIC_OFF | UNDERLINE_OFF | PROP_OFF)
  2628.     Message(&Menu, 1)               ! print key commands
  2629.     
  2630.     for (i=1; i<=num; i++)          ! print menu choices
  2631.     {
  2632.         color MENU_TEXTCOLOR, MENU_BGCOLOR
  2633.         locate column, (3+i)
  2634.         print menuitem[i]; to (column+width)
  2635.     }
  2636.     color TEXTCOLOR, BGCOLOR
  2637.  
  2638.     a = 1
  2639.     while true                      ! continuous loop
  2640.     {
  2641.         if a ~= olda
  2642.         {
  2643.             if olda ~= 0
  2644.                 {locate column, (3+olda)
  2645.                 color MENU_TEXTCOLOR, MENU_BGCOLOR
  2646.                 print menuitem[olda]; to (column+width)}
  2647.             color MENU_SELECTCOLOR, MENU_SELECTBGCOLOR
  2648.             locate column, (3+a)
  2649.             print menuitem[a]; to (column+width)
  2650.             color TEXTCOLOR, BGCOLOR
  2651.         }
  2652.         locate (column+width), (3+a)
  2653.         olda = a
  2654.         pause
  2655.         select word[0]
  2656.         case 'N', 'n', DOWN_ARROW, RIGHT_ARROW
  2657.         {
  2658.             a++
  2659.             if a > num:  a = 1
  2660.         }
  2661.         case 'P', 'p', UP_ARROW, LEFT_ARROW
  2662.         {
  2663.             if --a = 0:  a = num
  2664.         }
  2665.         case 'Q', 'q', ESCAPE_KEY
  2666.         {
  2667.             window:  print to linelength
  2668.             cls
  2669.             Font(DEFAULT_FONT)
  2670.             return 0
  2671.         }
  2672.         case ENTER_KEY
  2673.         {
  2674.             window:  print to linelength
  2675.             cls
  2676.             Font(DEFAULT_FONT)
  2677.             return a
  2678.         }
  2679.  
  2680.         if word[0] >= '0' and word[0] <= '9'
  2681.         {
  2682.             a = word[0] - '0'
  2683.             if a = 0:  a = 10
  2684.             if a > num:  a = olda
  2685.         }
  2686.     }
  2687. }    
  2688.  
  2689. routine CenterTitle(a)
  2690. {
  2691.     local l
  2692.  
  2693.     Font(PROP_OFF)
  2694.     l = string(_temp_string, a)
  2695.     window
  2696.     {
  2697.         color MENU_SELECTCOLOR, MENU_SELECTBGCOLOR
  2698.         print to (linelength/2 - l/2); a; to linelength
  2699.     }
  2700.     color TEXTCOLOR, BGCOLOR
  2701.     FONT(DEFAULT_FONT)
  2702.     cls
  2703.     locate 1,1
  2704. }
  2705.  
  2706. #endif  ! ifclear NO_MENUS
  2707.  
  2708. !\
  2709. *****************************************************************************
  2710.  
  2711. VERB ROUTINES:  (Globals verbroutine, object, and xobject (the latter two
  2712.         if applicable) are set up by the engine prior to calling.
  2713.  
  2714. *****************************************************************************
  2715. \!
  2716.  
  2717. #ifclear NO_VERBS
  2718.  
  2719. !----------------------------------------------------------------------------
  2720. routine DoVague
  2721. {
  2722.     Message(&DoVague)       ! "Be a little more specific..."
  2723.     return false
  2724. }
  2725.  
  2726. !----------------------------------------------------------------------------
  2727. ! FOR LOOKING AND EXAMINING:
  2728. !----------------------------------------------------------------------------
  2729. routine DoLookAround
  2730. {
  2731.     DescribePlace(location, true)
  2732.     return true
  2733. }
  2734.  
  2735. !----------------------------------------------------------------------------
  2736. routine DoLook
  2737. {
  2738.     local i, tempformat
  2739.     
  2740.     if not light_source
  2741.         Message(&DoLook, 1)     ! "It's too dark to see anything."
  2742.     else
  2743.     {
  2744.         if not object.long_desc
  2745.             ! "Looks just like you'd expect..."
  2746.             Message(&DoLook, 2)
  2747.         
  2748.         if object is living, transparent, not quiet
  2749.         {
  2750.             for i in object
  2751.             {
  2752.                 if i is not hidden
  2753.                     break
  2754.             }
  2755.             if i and object ~= player
  2756.             {
  2757.                 tempformat = FORMAT
  2758.                 FORMAT = FORMAT | NOINDENT_F
  2759.                 list_nest = 0
  2760.                 print ""
  2761.                 WhatsIn(object)
  2762.                 FORMAT = tempformat
  2763.             }
  2764.         }
  2765.         
  2766.         run object.after
  2767.         return true
  2768.     }
  2769. }
  2770.  
  2771. !----------------------------------------------------------------------------
  2772. routine DoLookIn
  2773. {
  2774.     local tempformat
  2775.     
  2776.     if not CheckReach(object):  return false
  2777.  
  2778.     if not light_source
  2779.         Message(&DoLook, 1)     ! "It's too dark to see anything."
  2780.     else
  2781.     {
  2782.         if object is container and (object is openable and
  2783.             object is not open and object is not transparent):
  2784.             Message(&DoLookIn, 1)           ! "It's closed."
  2785.         else
  2786.         {
  2787.             object is not quiet
  2788.  
  2789.             tempformat = FORMAT
  2790.             FORMAT = FORMAT | NOINDENT_F
  2791.             list_nest = 0
  2792.             
  2793.             if WhatsIn(object) = 0
  2794.                 Message(&DoLookIn, 2)   ! "It's empty."
  2795.             
  2796.             FORMAT = tempformat
  2797.         }
  2798.         run object.after
  2799.         return true
  2800.     }
  2801. }
  2802.  
  2803. !----------------------------------------------------------------------------
  2804. routine DoLookThrough
  2805. {
  2806.     if object is not static
  2807.         if not CheckReach(object)
  2808.             return false
  2809.     
  2810.     if object is transparent
  2811.     {
  2812.         if object is container or children(object)
  2813.             return Perform(&DoLookIn, object)
  2814.         else
  2815.             return Perform(&DoLook, object)
  2816.     }
  2817.  
  2818. #ifclear NO_OBJLIB
  2819.     elseif object.type = door
  2820.     {
  2821.         if object is not open
  2822.             Message(&DoLookIn, 1)   ! "It's closed."
  2823.         else
  2824.         {
  2825.             ! "Through it you can see..."
  2826.             Message(&DoLookThrough, 1)
  2827.  
  2828.             if location = object.found_in #1
  2829.                 print The(object.found_in #2); "."
  2830.             else
  2831.                 print The(object.found_in #1); "."
  2832.         }
  2833.         return true
  2834.     }
  2835. #endif
  2836.     else
  2837.         Message(&DoLookThrough, 2)  ! "You can't see through that."
  2838. }
  2839.  
  2840. !----------------------------------------------------------------------------
  2841. routine DoLookUnder
  2842. {
  2843.     if not CheckReach(object):  return false
  2844.  
  2845.     Message(&DoLookUnder, 1)        ! "You don't find anything."
  2846.     return true
  2847. }
  2848.  
  2849. !----------------------------------------------------------------------------
  2850. ! FOR WAITING AROUND:
  2851. !----------------------------------------------------------------------------
  2852. routine DoWait(count)                   ! count argument is from DoWaitUntil
  2853. {
  2854.     if object = 0
  2855.         count = 3
  2856.     elseif count = 0
  2857.         count = object
  2858.     
  2859.     Message(&DoWait)                ! "Time passes..."
  2860.     event_flag = 0
  2861.     while --count
  2862.     {
  2863.         main
  2864.         if event_flag
  2865.             if not KeepWaiting
  2866.                 return
  2867.     }
  2868.     event_flag = 0
  2869.     return true
  2870. }
  2871.  
  2872. !----------------------------------------------------------------------------
  2873. routine DoWaitforChar
  2874. {
  2875.     local count
  2876.  
  2877.     if object is not living
  2878.         {ParseError(6)
  2879.         return false}
  2880.  
  2881.     if object in location
  2882.     {
  2883.         Message(&DoWaitforChar, 1)      ! "They're right here..."
  2884.         return true
  2885.     }
  2886.  
  2887.     Message(&DoWait, 1)                     ! "Time passes..."
  2888.     event_flag = 0
  2889.     do
  2890.     {
  2891.         main
  2892.         if object in location
  2893.         {
  2894.             ! character has arrived
  2895.             Message(&DoWaitforChar, 2)
  2896.             event_flag = 0
  2897.             return
  2898.         }
  2899.         if event_flag
  2900.             if not KeepWaiting
  2901.                 return
  2902.         count++
  2903.     }
  2904.     while (STATUSTYPE=2 and count<60) or (STATUSTYPE~=2 and count<20)
  2905.  
  2906.     Message(&DoWaitforChar, 3)      ! character hasn't arrived yet
  2907.  
  2908.     event_flag = 0
  2909. }
  2910.  
  2911. !----------------------------------------------------------------------------
  2912. routine DoWaitUntil
  2913. {
  2914.     if object = counter
  2915.         {Message(&DoWaitUntil, 1)       ! "Wow.  Time flies."
  2916.         return}
  2917.     elseif object < counter and (STATUSTYPE ~= 2 or object > 720)
  2918.         {Message(&DoWaitUntil, 2)       ! "You're ahead of your time."
  2919.         return}
  2920.     else
  2921.     {     
  2922.         if object < counter
  2923.             object = object * 60
  2924.         
  2925.         DoWait(object - counter + 1)
  2926.         
  2927.         ! "It is now (whatever time/turn)..."
  2928.         Message(&DoWaitUntil, 3)
  2929.     }
  2930.     event_flag = 0
  2931. }
  2932.  
  2933. !----------------------------------------------------------------------------
  2934. routine KeepWaiting                     ! used by DoWait... routines
  2935. {
  2936.     event_flag = 0
  2937.     Message(&KeepWaiting)           ! "Keep waiting?"
  2938.     GetInput
  2939.     return YesorNo
  2940. }
  2941.  
  2942. !----------------------------------------------------------------------------
  2943. ! FOR TALKING TO CHARACTERS:
  2944. !----------------------------------------------------------------------------
  2945. routine DoTalk
  2946. {
  2947.     if word[2] = "to" and not xobject
  2948.     {
  2949.         if object is unfriendly
  2950.         {
  2951.             if not object.ignore_response
  2952.                 Message(&Speakto, 4)    ! "X ignores you."
  2953.             speaking = 0
  2954.         }
  2955.         elseif object = player
  2956.         {
  2957.             Message(&Speakto, 1)  ! "Stop talking to yourself."
  2958.             return false
  2959.         }
  2960.         else
  2961.         {
  2962.             speaking = object
  2963.             Message(&Speakto, 2)            ! "X is listening."
  2964. #ifclear NO_SCRIPTS
  2965.             SkipScript(object)
  2966. #endif
  2967.         }
  2968.         return true
  2969.     }
  2970.  
  2971.     Message(&DoTalk, 1)     ! "Tell or ask about something specific..."
  2972.     return false
  2973. }
  2974.  
  2975. !----------------------------------------------------------------------------
  2976. routine DoAsk
  2977. {
  2978.     if xobject = 0
  2979.     {
  2980.         Message(&DoAsk, 1)      ! "Ask about something specific..."
  2981.         return false
  2982.     }
  2983.  
  2984.     speaking = object
  2985.  
  2986.     if object is unfriendly
  2987.     {
  2988.         if not object.ignore_response
  2989.             Message(&Speakto, 4)    ! "X ignores you."
  2990.         speaking = 0
  2991.     }
  2992.     elseif object = player
  2993.         {Message(&DoAsk, 2)             ! "Talking to yourself..."
  2994.         return false}
  2995.     elseif xobject = player
  2996.         Message(&DoAsk, 3)              ! asking about yourself
  2997.     elseif xobject = object
  2998.     {
  2999.         if not object.after
  3000.             Message(&DoAsk, 4)      ! asking about him/herself
  3001.     }
  3002.     else
  3003.     {
  3004.         if xobject in location and xobject is living
  3005.             
  3006.             ! "Not while the other person is in the room..."
  3007.             Message(&DoAsk, 5)
  3008.  
  3009.         elseif not object.after
  3010.             
  3011.             ! "Doesn't seem to know anything..."
  3012.             Message(&DoAsk, 6)
  3013.  
  3014. #ifclear NO_SCRIPTS
  3015.         SkipScript(object)
  3016. #endif
  3017.     }
  3018.     return true
  3019. }
  3020.  
  3021. !----------------------------------------------------------------------------
  3022. routine DoAskQuestion
  3023. {
  3024.     if speaking = 0
  3025.         {Message(&DoAskQuestion)        ! "Not talking to anybody..."
  3026.         return false}
  3027.     elseif xobject
  3028.         {ParseError(6)
  3029.         return false}
  3030.     
  3031.     return Perform(&DoAsk, speaking, object)
  3032. }
  3033.  
  3034. !----------------------------------------------------------------------------
  3035. routine DoTell
  3036. {
  3037.     if object = player
  3038.         Message(&DoAsk, 2)      ! "Talking to yourself..."
  3039.     
  3040.     if xobject = 0
  3041.         {Message(&DoTell, 1)    ! "Tell about something specific..."
  3042.         return false}
  3043.  
  3044.     speaking = object
  3045.     
  3046.     
  3047.     if object is unfriendly
  3048.     {
  3049.         if not object.ignore_response
  3050.             Message(&Speakto, 4)    ! "X ignores you."
  3051.         speaking = 0
  3052.     }
  3053.     else
  3054.     {
  3055.         if not object.after
  3056.             Message(&DoTell, 2)     ! "Not interested..."
  3057. #ifclear NO_SCRIPTS
  3058.         SkipScript(object)
  3059. #endif
  3060.     }
  3061.     return true
  3062. }
  3063.  
  3064. !----------------------------------------------------------------------------
  3065. routine DoListen
  3066. {
  3067.     if not object
  3068.         {Message(&DoListen, 1)  ! "Be a little more specific..."
  3069.         return false}
  3070.     elseif not object.after
  3071.         Message(&DoListen, 2)   ! "Not making any sound..."
  3072.     return true
  3073. }
  3074.  
  3075. !----------------------------------------------------------------------------
  3076. ! FOR MOVING AROUND
  3077. !----------------------------------------------------------------------------
  3078.  
  3079. ! (Credit for the implementation of generic directions goes to Julian Arnold)
  3080.  
  3081. routine DoGo
  3082. {
  3083.     local wordnum, moveto, m, obj
  3084.  
  3085.     if obstacle
  3086.     {
  3087.         Message(&DoGo, 1)               ! "X stops you from going..."
  3088.         return true
  3089.     }
  3090.     elseif player not in location           ! i.e. a vehicle, etc.
  3091.     {
  3092.         if parent(player).before 
  3093.             return true
  3094.     }
  3095.  
  3096.     ! See if the object is one of the current direction set
  3097.     if object.type = direction and object in direction
  3098.     {
  3099.         moveto = object
  3100.         jump FoundDirection
  3101.     }
  3102.     
  3103.     wordnum = 1                             ! various phrasings
  3104.     if words > 1 and word[2] ~= ""
  3105.         wordnum = 2
  3106.     if word[2] = "to", "through"
  3107.         wordnum = 3
  3108.     elseif (word[2] = "in" or word[2] = "inside") and words > 2
  3109.         wordnum = 3
  3110.  
  3111. #ifclear NO_OBJLIB
  3112.     for obj in direction
  3113.     {
  3114.         if obj.type = direction and ObjWord(word[wordnum],obj)
  3115.             moveto = obj
  3116.     }
  3117.  
  3118.     if not moveto
  3119.     {
  3120. #endif
  3121. #ifset NO_OBJLIB
  3122.     select word[wordnum]
  3123.         case "north", "n":      m = n_to
  3124.         case "south", "s":      m = s_to
  3125.         case "east", "e":       m = e_to
  3126.         case "west", "w":       m = w_to
  3127.         case "northwest", "nw": m = nw_to
  3128.         case "northeast", "ne": m = ne_to
  3129.         case "southeast", "se": m = se_to
  3130.         case "southwest", "sw": m = sw_to
  3131.         case "up", "u":         m = u_to
  3132.         case "down", "d":       m = d_to
  3133.         case "in", "inside":    m = in_to
  3134.         case "out", "outside":  m = out_to
  3135.  
  3136.     if not m
  3137.     {
  3138. #endif
  3139.  
  3140.         if not object           
  3141.             {ParseError(6)  ! doesn't make any sense
  3142.             return}
  3143.  
  3144.         if not &object.door_to
  3145.         {
  3146.             if not object.door_to and object is enterable
  3147.                 return Perform(&DoEnter, object)
  3148.         }
  3149.  
  3150.         moveto = object.door_to
  3151.         if not moveto
  3152.             {Message(&DoEnter, 2)  ! "You can't enter..."
  3153.             return}
  3154.         if moveto = 1
  3155.             return true
  3156.     }
  3157.  
  3158. :FoundDirection
  3159.  
  3160. #ifclear NO_OBJLIB
  3161.     if moveto.type = direction and moveto in direction
  3162.     {
  3163.         if not object
  3164.         {
  3165.             object = moveto
  3166.             if object.before
  3167.                 return true
  3168.         }
  3169.         else:  object = moveto
  3170.         moveto = location.(moveto.dir_to)
  3171.     }
  3172. #endif
  3173. #ifset NO_OBJLIB
  3174.     if m
  3175.     {
  3176.         object = m
  3177.         moveto = location.m
  3178.     }
  3179. #endif
  3180.  
  3181.     if moveto = false
  3182.     {
  3183.         if not location.cant_go
  3184.             Message(&DoGo, 2)       ! "You can't go that way."
  3185.         object = 0
  3186.         return false
  3187.     }
  3188.     
  3189.     elseif moveto = true                    ! already printed message
  3190.         {object = 0                     ! (moveto is never 1)
  3191.         return true}
  3192.     
  3193.     elseif player not in location           ! sitting on or in an obj.
  3194.  
  3195.         Message(&DoGo, 3)               ! "You'll have to get up..."
  3196.     else
  3197.     {
  3198.         m = verbroutine                 ! check room exiting
  3199.         verbroutine = &DoExit
  3200.         if location.before
  3201.             return true
  3202.         verbroutine = m
  3203.  
  3204.         MovePlayer(moveto)
  3205.  
  3206.         object = 0
  3207.         return true
  3208.     }
  3209.     object = 0
  3210. }
  3211.  
  3212. !----------------------------------------------------------------------------
  3213. ! Note that DoEnter and DoExit expect the preposition (alias prep) property 
  3214. ! to hold the equivalent of "in" and "out" for the enterable object in 
  3215. ! question; if there is no preposition property, "in" and "out" are the
  3216. ! defaults.
  3217.  
  3218. routine DoEnter
  3219. {
  3220.     if not object
  3221.     {
  3222.         Message(&DoEnter, 1)    ! "Be a little more specific..."
  3223.         return false
  3224.     }
  3225.     
  3226.     if &object.door_to
  3227.         return Perform(&DoGo, object)   ! routine
  3228.     elseif object.door_to
  3229.         return Perform(&DoGo, object)   ! object
  3230.  
  3231.     if object is not enterable or Contains(player, object)
  3232.         Message(&DoEnter, 2)    ! "You can't enter that."
  3233.     elseif player in object
  3234.         Message(&DoEnter, 3)    ! already in it
  3235.     elseif player not in location
  3236.         Message(&DoGo, 3)       ! "You'll have to get up..."
  3237.     elseif object is openable, not open
  3238.         Message(&DoLookIn, 1)   ! "X is closed."
  3239.     else
  3240.     {
  3241.         move player to object
  3242.         if not object.after
  3243.             Message(&DoEnter, 4)    ! "You get in..."
  3244.         object is not quiet
  3245.         return true
  3246.     }
  3247.     return
  3248. }
  3249.  
  3250. !----------------------------------------------------------------------------
  3251. routine DoExit
  3252. {
  3253.     local p
  3254.     
  3255.     if object = nothing or object = location
  3256.     {
  3257.         if player in location and out_obj in direction
  3258.             {word[1] = out_obj.noun
  3259.             word[2] = ""
  3260.             return Perform(&DoGo)}
  3261.     }
  3262.  
  3263.     p = parent(player)
  3264.   
  3265.     if object and player not in object
  3266.         Message(&DoExit, 1)             ! "You aren't in that."
  3267.     elseif p is openable, not open
  3268.         Message(&DoLookIn, 1)           ! "X is closed."
  3269.     else
  3270.     {
  3271.         if object = nothing
  3272.             object = p
  3273.         move player to location
  3274.         if not object.after
  3275.             Message(&DoExit, 2)     ! "You get out.."
  3276.     }
  3277.     return true
  3278. }
  3279.  
  3280. !----------------------------------------------------------------------------
  3281. ! FOR MANIPULATING OBJECTS:
  3282. !----------------------------------------------------------------------------
  3283. routine DoInventory
  3284. {
  3285.     local tempformat
  3286.  
  3287.     if word[2] = "tall"
  3288.         INVENTORY_MASK = INVENTORY_MASK | LIST_F
  3289.     elseif word[2] = "wide"
  3290.         INVENTORY_MASK = INVENTORY_MASK & ~LIST_F
  3291.     
  3292.     tempformat = FORMAT
  3293.     FORMAT = FORMAT | INVENTORY_F | GROUPPLURALS_F | NOINDENT_F
  3294.     FORMAT = FORMAT | INVENTORY_MASK
  3295.     list_nest = 0
  3296.     if not WhatsIn(player)
  3297.         Message(&DoInventory)   ! "You aren't carrying anything."
  3298.     FORMAT = tempformat
  3299.     
  3300.     return true
  3301. }
  3302.  
  3303. !----------------------------------------------------------------------------
  3304. routine DoClose
  3305. {
  3306.     if not CheckReach(object):  return false
  3307.  
  3308.     if object is not openable
  3309.     {
  3310.         Message(&DoClose, 1)            ! "You can't close that."
  3311.         return
  3312.     }
  3313.     elseif object is not open
  3314.         Message(&DoClose, 2)            ! "It's already closed."
  3315.     else
  3316.     {
  3317.         object is not open
  3318.         object is moved
  3319.         if not object.after
  3320.             Message(&DoClose, 3)    ! "Closed."
  3321.  
  3322.         if not FindLight(location)      ! in case the light source
  3323.                         ! has been concealed
  3324.             
  3325.             Message(&DoClose, 4)    ! "Everything goes dark."
  3326.     }
  3327.     return true
  3328. }
  3329.  
  3330. !----------------------------------------------------------------------------
  3331. routine DoOpen
  3332. {
  3333.     local tempformat
  3334.  
  3335.     if not CheckReach(object):  return false
  3336.  
  3337.     if object is not openable
  3338.     {
  3339.         Message(&DoOpen, 1)             ! "You can't open that."
  3340.         return
  3341.     }
  3342.     elseif object is open
  3343.         Message(&DoOpen, 2)             ! "It's already closed."
  3344.     elseif object is locked
  3345.         Message(&DoOpen, 3)             ! "It's locked."
  3346.     else
  3347.     {
  3348.         object is open
  3349.         object is moved
  3350.         if not object.after
  3351.         {
  3352.             Message(&DoOpen, 4)     ! "Opened."
  3353.  
  3354.             FindLight(location)     ! in case the light source
  3355.                         ! has been revealed
  3356.             if children(object) and object is not quiet
  3357.             {
  3358.                 print ""
  3359.                 tempformat = FORMAT
  3360.                 FORMAT = FORMAT | NOINDENT_F
  3361.                 list_nest = 0
  3362.                 WhatsIn(object)
  3363.                 FORMAT = tempformat
  3364.             }
  3365.         }
  3366.     }
  3367.     return true
  3368. }
  3369.  
  3370. !----------------------------------------------------------------------------
  3371. routine DoMove
  3372. {
  3373.     if not CheckReach(object):  return false
  3374.  
  3375.     Message(&DoMove)                ! "You can't move that."
  3376.     return true
  3377. }
  3378.  
  3379. !----------------------------------------------------------------------------
  3380. routine DoGet
  3381. {
  3382.     local b, p
  3383.     
  3384.     if object in player
  3385.         Message(&DoGet, 1)      ! "You already have that."
  3386.     elseif object = player
  3387.         {Message(&DoGet, 2)     ! player trying to get player
  3388.         return false}
  3389.     elseif object is living and object is static
  3390.         {Message(&DoGet, 3)     ! player trying to get character
  3391.         return false}
  3392.     elseif parent(object) is living and parent(object) is unfriendly
  3393.         Message(&DoGet, 4)      ! "X doesn't want to give it to you."
  3394.     elseif (parent(object) is openable, not open) and
  3395.         parent(object) is container:
  3396.         {Message(&DoGet, 5)     ! "X is closed."
  3397.         return false}
  3398.     elseif Contains(object, player)
  3399.         {Message(&DoGet, 6)     ! "Not while you're in/on it..."
  3400.         return false}
  3401.     else
  3402.     {
  3403.         if not CheckReach(object)
  3404.             return false
  3405.         elseif object is static
  3406.         {
  3407.             Message(&DoGet, 7)      ! "You can't take that."
  3408.             return true
  3409.         }
  3410.  
  3411.         ! Because the engine calls location.before
  3412.         if (parent(object)~=location)
  3413.             b = parent(object).before
  3414.  
  3415.         if not b
  3416.         {
  3417.             xobject = parent(object)
  3418.  
  3419.             if object not in location
  3420.                 {CalculateHolding(xobject)
  3421.                 p = xobject}
  3422.  
  3423.             if Acquire(player, object)
  3424.             {
  3425.                 ! if object was in something
  3426.                 if p
  3427.                     p.holding = p.holding - object.size
  3428.  
  3429.                 object is not hidden
  3430.                 
  3431.                 if not object.after
  3432.                 {
  3433.                     ! Again, to avoid duplication or
  3434.                     ! echoing:
  3435.                     !
  3436.                     b = 0
  3437.                     if xobject ~= location
  3438.                         b = xobject.after
  3439.  
  3440.                     if b = false
  3441.                         ! "Taken."
  3442.                         Message(&DoGet, 8)
  3443.                 }
  3444.             }
  3445.             else
  3446.                 ! "You're carrying too much to take that."
  3447.                 Message(&DoGet, 9)
  3448.         }
  3449.     }
  3450.     return true
  3451. }
  3452.  
  3453. !----------------------------------------------------------------------------
  3454. routine DoDrop
  3455. {
  3456.     if object is clothing and object is worn
  3457.         Message(&DoDrop, 1)     ! "You'll have to take it off first."
  3458.     
  3459.     ! For the following, xobject is true only 
  3460.     ! when called by DoPutonGround:
  3461.     
  3462.     elseif player not in location and (parent(player) is container or
  3463.         parent(player) is platform) and not xobject:
  3464.  
  3465.         Perform(&DoPutIn, object, parent(player))
  3466.     else
  3467.     {
  3468.         move object to location
  3469.         object is moved
  3470.         player.holding = player.holding - object.size
  3471.         if not object.after
  3472.             Message(&DoDrop, 2)     ! "Dropped."
  3473.     }
  3474.     xobject = 0
  3475.     return true
  3476. }
  3477.  
  3478. routine DoPutonGround                   ! to override vehicles, etc.
  3479. {
  3480.     if xobject and player not in xobject
  3481.     {
  3482.         Message(&DoPutonGround, 1)      ! "You aren't in X."
  3483.         return false
  3484.     }
  3485.     xobject = 1
  3486.     return Perform(&DoDrop, object, xobject)
  3487. }
  3488.  
  3489. !----------------------------------------------------------------------------
  3490. routine DoPutIn
  3491. {
  3492.     if not xobject
  3493.         Message(&DoPutIn, 1)    ! "Put it in what?"
  3494.     elseif object is clothing and object is worn
  3495.         Message(&DoDrop, 1)     ! "Have to take it off first..."
  3496.     elseif xobject is container, openable, not open
  3497.         Message(&DoPutIn, 2)    ! "It's closed."
  3498.     elseif object = xobject
  3499.         Message(&DoPutIn, 3)    ! putting something in itself
  3500.     elseif xobject is not container and xobject is not platform
  3501.         Message(&DoPutIn, 3)    ! "Can't do that."
  3502.     elseif Contains(object, xobject)
  3503.         Message(&DoPutIn, 4)    ! putting a parent in its child
  3504.     elseif CheckReach(object) 
  3505.     {
  3506.         if CheckReach(xobject)
  3507.         {
  3508.             if Acquire(xobject,object)
  3509.             {
  3510.                 player.holding = player.holding - object.size
  3511.                 if not xobject.after
  3512.                     ! "You put X in/on Y."
  3513.                     Message(&DoPutIn, 5)
  3514.             }
  3515.             else
  3516.                 ! "There's no room..."
  3517.                 Message(&DoPutIn, 6)
  3518.         }
  3519.     }
  3520.     return true
  3521. }
  3522.  
  3523. !----------------------------------------------------------------------------
  3524. routine DoEmpty
  3525. {
  3526.     local a, b, obj, xobj
  3527.     
  3528.     CalculateHolding(object)
  3529.     
  3530.     if object is container, openable, not open 
  3531.         {Message(&DoEmpty, 1)           ! "It's closed."
  3532.         return true}
  3533.     if not children(object)
  3534.         {Message(&DoEmpty, 2)           ! "It's already empty."
  3535.         return true}
  3536.  
  3537.     while child(object)
  3538.     {
  3539.         print child(object).name; ":  ";
  3540.         
  3541.         if child(object) is static
  3542.             Message(&DoEmpty, 3)    ! "You can't move that."
  3543.         else                
  3544.         {
  3545.             a = player.holding
  3546.             b = child(object)
  3547.             obj = object
  3548.             xobj = xobject
  3549.  
  3550.             if player not in location and
  3551.                 (parent(player) is platform or
  3552.                     parent(player) is container) and
  3553.                 not xobject:
  3554.                 
  3555.                 Perform(&DoPutIn, b, parent(player))
  3556.             else
  3557.                 Perform(&DoDrop, b)
  3558.  
  3559.             object = obj
  3560.             xobject = xobj
  3561.             player.holding = a
  3562.             if b not in object
  3563.                 object.holding = object.holding - b.size
  3564.         }
  3565.     }
  3566.  
  3567.     run object.after
  3568.     return true
  3569. }
  3570.  
  3571. routine DoEmptyGround                   ! to override vehicles, etc.
  3572. {
  3573.     xobject = 1
  3574.     return Perform(&DoEmpty, object, xobject)
  3575. }
  3576.  
  3577. !----------------------------------------------------------------------------
  3578. routine DoGive
  3579. {
  3580.     local a
  3581.     
  3582.     if not xobject
  3583.         {Message(&DoGive, 1)    ! "Be more specific..."
  3584.         return false}
  3585.  
  3586.     if object not in player
  3587.     {
  3588.         if not FindObject(object, location)
  3589.             ParseError(11, object)
  3590.         Message(&DoGive, 5)     ! "(taking it first)"
  3591.         Perform(&DoGet, object)
  3592.         if object not in player
  3593.             return false
  3594.         main                    ! counts as a turn
  3595.         a = true
  3596.     }
  3597.     
  3598.     if object is clothing, worn
  3599.         {Message(&DoDrop, 1)    ! "Have to take it off first..."
  3600.         return false}
  3601.  
  3602.     if xobject = player
  3603.         {Message(&DoGive, 2)    ! player giving something to player
  3604.         return false}
  3605.     
  3606.     if a:  print ""
  3607.     
  3608.     if not object.after
  3609.     {
  3610.         if not xobject.after
  3611.         {
  3612.             if xobject is not living
  3613.                 ! "Your kind gesture goes unnoticed."
  3614.                 Message(&DoGive, 3)
  3615.             else
  3616.                 ! "X politely refuses."
  3617.                 Message(&DoGive, 4)
  3618.         }
  3619.     }
  3620.     return true
  3621. }
  3622.  
  3623. !----------------------------------------------------------------------------
  3624. routine DoShow
  3625. {
  3626.     if not xobject
  3627.         {Message(&DoShow, 1)    ! "Be more specific..."
  3628.         return false}
  3629.     
  3630.     if not object.after
  3631.     {
  3632.         if not xobject.after
  3633.         {
  3634.             if xobject is not living
  3635.                 ! showing it to something inanimate
  3636.                 Message(&DoShow, 2)
  3637.             else
  3638.                 ! character ignores it
  3639.                 Message(&DoShow, 3)
  3640.         }
  3641.     }
  3642.     return true
  3643. }
  3644.  
  3645. !----------------------------------------------------------------------------
  3646. routine DoWear
  3647. {
  3648.     local a
  3649.     
  3650.     if object is not clothing
  3651.         {Message(&DoWear, 1)    ! "You can't wear that."
  3652.         return false}
  3653.  
  3654.     if object not in player
  3655.     {
  3656.         if not FindObject(object, location)
  3657.             ParseError(11, object)
  3658.         Message(&DoGive, 5)     ! "(taking it first)"
  3659.         Perform(&DoGet, object)
  3660.         if object not in player
  3661.             return false
  3662.         main                    ! counts as a turn
  3663.         a = true
  3664.     }
  3665.  
  3666.     if object is worn
  3667.         Message(&DoWear, 2)     ! "Already wearing that..."
  3668.     else
  3669.     {
  3670.         if a:  print ""
  3671.         object is worn
  3672.         if not object.after
  3673.             Message(&DoWear, 3)     ! "You put it on."
  3674.     }
  3675.     return true
  3676. }
  3677.  
  3678. !----------------------------------------------------------------------------
  3679. routine DoTakeOff
  3680. {
  3681.     if object is not clothing
  3682.         {Message(&DoTakeOff, 1)         ! "Can't do that..."
  3683.         return false}
  3684.  
  3685.     if object is not worn
  3686.         Message(&DoTakeOff, 2)          ! "You're not wearing that."
  3687.     else
  3688.     {
  3689.         object is not worn
  3690.         if not object.after
  3691.             Message(&DoTakeOff, 3)  ! "You take it off."
  3692.     }
  3693.     return true
  3694. }
  3695.  
  3696. !----------------------------------------------------------------------------
  3697. routine DoSwitchOn
  3698. {
  3699.     if not CheckReach(object):  return false
  3700.  
  3701.     if object is switchedon
  3702.         Message(&DoSwitchOn, 1)         ! "It's already on."
  3703.     else
  3704.     {
  3705.         object is switchedon
  3706.         if not object.after
  3707.             Message(&DoSwitchOn, 2)         ! "Switched on."
  3708.     }
  3709.     return true
  3710. }
  3711.  
  3712. !----------------------------------------------------------------------------
  3713. routine DoSwitchOff
  3714. {
  3715.     if not CheckReach(object):  return false
  3716.  
  3717.     if object is not switchedon
  3718.         Message(&DoSwitchOff, 1)        ! "It's already off."
  3719.     else
  3720.     {
  3721.         object is not switchedon
  3722.         if not object.after
  3723.             Message(&DoSwitchOff, 2)        ! "Switched off."
  3724.     }
  3725.     return true
  3726. }
  3727.  
  3728. !----------------------------------------------------------------------------
  3729. routine DoUnlock
  3730. {
  3731.     if not CheckReach(object):  return false
  3732.  
  3733.     if xobject ~= 0
  3734.     {
  3735.         if object.key_object ~= xobject
  3736.             {Message(&DoUnlock, 1)  ! "Doesn't seem to work..."
  3737.             return true}
  3738.     }
  3739.     elseif object.key_object and object.key_object not in player
  3740.     {
  3741.         Message(&DoUnlock, 2)           ! no key that fits
  3742.         return true
  3743.     }
  3744.  
  3745.     if object is not locked
  3746.         Message(&DoUnlock, 3)           ! already unlocked
  3747.     else
  3748.     {
  3749.         object is not locked
  3750.         if not object.after
  3751.         {
  3752.             if not xobject.after
  3753.                 Message(&DoUnlock, 4)   ! "Unlocked."
  3754.         }
  3755.     }
  3756.     return true
  3757. }
  3758.  
  3759. !----------------------------------------------------------------------------
  3760. routine DoLock
  3761. {
  3762.     if not CheckReach(object):  return false
  3763.  
  3764.     if xobject ~= 0
  3765.     {
  3766.         if object.key_object ~= xobject
  3767.             {Message(&DoUnlock, 1)  ! "Doesn't seem to work..."
  3768.             return true}
  3769.     }
  3770.     elseif object.key_object and object.key_object not in player
  3771.     {
  3772.         Message(&DoUnlock, 2)           ! no key that fits
  3773.         return true
  3774.     }
  3775.  
  3776.     if object is locked
  3777.         Message(&DoLock, 1)             ! already locked
  3778.     elseif object is open
  3779.         Message(&DoLock, 2)             ! "Have to close it first..."
  3780.     else
  3781.     {
  3782.         object is locked
  3783.         if not object.after
  3784.         {
  3785.             if not xobject.after
  3786.                 Message(&DoLock, 3)     ! "Locked."
  3787.         }
  3788.     }
  3789.     return true
  3790. }
  3791.  
  3792. !----------------------------------------------------------------------------
  3793. routine DoEat
  3794. {
  3795.     if not object.after
  3796.         Message(&DoEat)         ! "You can't eat that."
  3797. }
  3798.  
  3799. !----------------------------------------------------------------------------
  3800. routine DoDrink
  3801. {
  3802.     if not object.after
  3803.         Message(&DoDrink)       ! "You can't drink that."
  3804. }
  3805.  
  3806. !----------------------------------------------------------------------------
  3807. routine DoHit
  3808. {
  3809.     if not object.after
  3810.         Message(&DoHit)         ! "Doesn't accomplish much..."
  3811. }
  3812.  
  3813. #endif  ! ifclear NO_VERBS
  3814.  
  3815. !----------------------------------------------------------------------------
  3816. ! NON-ACTION VERBS:
  3817. !----------------------------------------------------------------------------
  3818.  
  3819. #ifclear NO_XVERBS
  3820.  
  3821. routine DoHello
  3822.     {Message(&DoHello)}
  3823.  
  3824. routine DoBrief
  3825.     {Message(&DoBrief)
  3826.     verbosity = 0}
  3827.  
  3828. routine DoSuperbrief
  3829.     {Message(&DoSuperBrief)
  3830.     verbosity = 1}
  3831.  
  3832. routine DoVerbose
  3833.     {Message(&DoVerbose)
  3834.     verbosity = 2}
  3835.  
  3836. routine DoDisplay
  3837. {
  3838.     if word[1] = "tall" or word[2] = "tall"
  3839.     {
  3840.         Message(&DoDisplay, 1)          ! "Tall listings."
  3841.         FORMAT = FORMAT | LIST_F
  3842.     }
  3843.     elseif word[1] = "wide" or word[2] = "wide"
  3844.     {
  3845.         Message(&DoDisplay, 2)          ! "Wide listings."
  3846.         FORMAT = FORMAT & ~LIST_F
  3847.     }
  3848.     else
  3849.         Message(&DoDisplay, 3)          ! instructions
  3850. }
  3851.  
  3852. !----------------------------------------------------------------------------
  3853. routine DoSave
  3854. {
  3855.     if save
  3856.         Message(&DoSave, 1)             ! "Saved."
  3857.     else:  Message(&DoSave, 2)              ! "Unable to save."
  3858. }
  3859.  
  3860. !----------------------------------------------------------------------------
  3861. routine DoRestore
  3862. {
  3863.     if restore
  3864.         {Message(&DoRestore, 1)         ! "Restored."
  3865.         PrintStatusline
  3866.         DescribePlace(location, true)}
  3867.     else:  Message(&DoRestore, 2)           ! "Unable to restore."
  3868. }
  3869.  
  3870. !----------------------------------------------------------------------------
  3871. routine DoQuit
  3872. {
  3873.     PrintScore
  3874.     Message(&DoQuit)                        ! "Are you sure?"
  3875.     GetInput
  3876.     if YesorNo = true {quit}
  3877. }
  3878.  
  3879. !----------------------------------------------------------------------------
  3880. routine DoRestart
  3881. {
  3882.     Message(&DoRestart, 1)                  ! "Are you sure?"
  3883.     GetInput
  3884.     if YesorNo = true 
  3885.     {
  3886.         if restart
  3887.             PrintStatusline
  3888.         else
  3889.             Message(&DoRestart, 2)  ! "Unable to restart."
  3890.     }
  3891. }
  3892.  
  3893. !----------------------------------------------------------------------------
  3894. routine DoScriptOnOff
  3895. {
  3896.     if word[2] = "on" or words = 1
  3897.     {
  3898.         if not scripton
  3899.             Message(&DoScriptOnOff, 1)      ! "Unable to begin..."
  3900.         else
  3901.             Message(&DoScriptOnOff, 2)      ! "Transcription on."
  3902.     }
  3903.     elseif word[2] = "off"
  3904.     {
  3905.         if not scriptoff
  3906.             Message(&DoScriptOnOff, 3)      ! "Unable to end..."
  3907.         else
  3908.             Message(&DoScriptOnOff, 4)      ! "Transcription off."
  3909.     }
  3910. }
  3911.  
  3912. !----------------------------------------------------------------------------
  3913. #ifclear NO_RECORDING
  3914. routine DoRecordOnOff
  3915. {
  3916.     if word[1] = "playback"
  3917.     {
  3918.         if not playback
  3919.             Message(&DoRecordOnOff, 1)  ! "Unable to begin..."
  3920.         else
  3921.             Message(&DoRecordOnOff, 2)  ! "Playback beginning..."
  3922.     }
  3923.     elseif word[2] = "on" or words = 1
  3924.     {
  3925.         if not recordon
  3926.             Message(&DoRecordOnOff, 3)  ! "Unable to begin..."
  3927.         else
  3928.             Message(&DoRecordOnOff, 4)  ! "Recording on."
  3929.     }
  3930.     elseif word[2] = "off"
  3931.     {
  3932.         if not recordoff
  3933.             Message(&DoRecordOnOff, 5)  ! "Unable to end..."
  3934.         else
  3935.             Message(&DoRecordOnOff, 6)  ! "Recording off."
  3936.     }
  3937. }
  3938. #endif
  3939.  
  3940. !----------------------------------------------------------------------------
  3941. routine DoScore
  3942. {
  3943.     if STATUSTYPE ~= 1
  3944.         Message(&DoScore)               ! no scorekeeping
  3945.     else
  3946.         PrintScore
  3947. }
  3948.  
  3949. !----------------------------------------------------------------------------
  3950. routine DoUndo
  3951. {
  3952.     if not UNDO_OFF
  3953.     {
  3954.         if undo
  3955.             {PrintStatusline
  3956.             DescribePlace(location)}
  3957.         else
  3958.             Message(&DoUndo)
  3959.     }
  3960.     else
  3961.         Message(&DoUndo)
  3962. }
  3963.  
  3964. #endif  ! ifclear NO_XVERBS
  3965.  
  3966. !\
  3967. *****************************************************************************
  3968.  
  3969. FUSE AND DAEMON CLASSES AND ROUTINES
  3970.  
  3971. *****************************************************************************
  3972. \!
  3973.  
  3974. #ifclear NO_FUSES
  3975.  
  3976. attribute active alias known
  3977.  
  3978. property timer alias n_to               ! for fuses only
  3979. property tick alias ne_to               !
  3980.  
  3981. class fuse "fuse"
  3982. {
  3983.     type fuse
  3984.     size 0
  3985.     timer 0
  3986.     in_scope 0
  3987.     tick 
  3988.     {
  3989.         if --self.timer < 0
  3990.             self.timer = 0
  3991.         
  3992. #ifset DEBUG
  3993.         if debug_flags & D_FUSES
  3994.         {        
  3995.             print "[Running fuse "; number self; ":  timer = ";
  3996.             print number self.timer; "]"
  3997.         }
  3998. #endif
  3999.  
  4000.         if self.timer = 0
  4001.             Deactivate(self)
  4002.         return self.timer
  4003.     }
  4004. }
  4005.  
  4006. class daemon "daemon"
  4007. {
  4008.     type daemon
  4009.     size 0
  4010.     in_scope 0
  4011. }
  4012.  
  4013. routine Activate(a, set)                ! <set> is for fuses only
  4014. {
  4015.     a.in_scope = player
  4016.     a is active
  4017.     if a.type = fuse
  4018.         a.timer = set
  4019.     elseif a.type = daemon and set
  4020.         print "[WARNING:  Attempt to set timer property 
  4021.         on daemon (object "; number a; ")]"
  4022.     elseif a.type ~= daemon
  4023.         print "[WARNING:  Attempt to activate non-fuse/\
  4024.         daemon (object "; number a; ")]"
  4025.     
  4026. #ifset DEBUG      
  4027.     if debug_flags & D_FUSES
  4028.     {
  4029.         print "[Activating "; a.name; " "; number a;
  4030.         if a.type = fuse
  4031.             print " (timer = "; number a.timer; ")";
  4032.         print "]"
  4033.     }
  4034. #endif
  4035.  
  4036. }
  4037.  
  4038. routine Deactivate(a)
  4039. {
  4040.     remove a
  4041.     a.in_scope = 0
  4042.     a is not active
  4043.     
  4044.     if a.type ~= fuse and a.type ~= daemon
  4045.         print "[WARNING:  Attempt to deactivate non-fuse/\
  4046.         daemon (object "; number a; ")]"
  4047.  
  4048. #ifset DEBUG
  4049.     if debug_flags & D_FUSES
  4050.     {
  4051.         print "[Deactivating "; a.name; " "; number a; "]"
  4052.     }
  4053. #endif
  4054.  
  4055. }
  4056.  
  4057. #endif  ! ifclear NO_FUSES
  4058.  
  4059.  
  4060. !\
  4061. *****************************************************************************
  4062.  
  4063. CHARACTER SCRIPT ROUTINES
  4064.  
  4065. *****************************************************************************
  4066. \!
  4067.  
  4068. #ifclear NO_SCRIPTS
  4069.  
  4070. !----------------------------------------------------------------------------
  4071. ! x = Script(character, number of steps)
  4072. ! initializes space for the script, and returns its location in the
  4073. ! setscript array; returns -1 if MAX_SCRIPTS is exceeded
  4074. !
  4075. ! SYNTAX:  setscript[script(char, steps)] =  &CharRoutine_1, object_1,
  4076. !                                            &CharRoutine_2, object_2,
  4077. !                                            ...
  4078. !                                            (maximum of 32 steps)
  4079.  
  4080. routine Script(obj, steps)
  4081. {
  4082.     local o
  4083.  
  4084.     o = 0
  4085.     while scriptdata[o * 3] ~= obj and scriptdata[o * 3] ~= 0 and
  4086.         o < MAX_SCRIPTS:
  4087.         o++
  4088.     if o = MAX_SCRIPTS
  4089.         return -1 
  4090.     if scriptdata[o * 3] = 0
  4091.         {scriptdata[o * 3] = obj                ! the object
  4092.         number_scripts++}
  4093.     scriptdata[o * 3 + 1] = 0                       ! starting step
  4094.     scriptdata[o * 3 + 2] = steps                   ! total no. of steps
  4095.     return o * MAX_SCRIPTS * 2
  4096. }
  4097.  
  4098. routine FindScript(obj)
  4099. {
  4100.     local o
  4101.  
  4102.     o = 0
  4103.     while scriptdata[o * 3] ~= obj and o < MAX_SCRIPTS:  o++
  4104.     return o
  4105. }
  4106.  
  4107. #endif  ! ifclear NO_SCRIPTS
  4108.  
  4109. !----------------------------------------------------------------------------
  4110. ! RunScripts
  4111. ! runs all active character scripts via:  CharRoutine(character, object)
  4112.  
  4113. routine RunScripts
  4114. {
  4115.  
  4116. #ifclear NO_SCRIPTS
  4117.  
  4118.     local a, obj, step, total, routine, b
  4119.     local tempactor, tempverb, tempobject
  4120.  
  4121.     for (; a<number_scripts; a++)
  4122.     {
  4123.         obj = scriptdata[a * 3]         ! this object/character
  4124.         step = scriptdata[a * 3 + 1]    ! current step
  4125.         total = scriptdata[a * 3 + 2]   ! total steps in script
  4126.  
  4127.         if obj and total < 0            ! if skipping this script
  4128.             scriptdata[a * 3 + 2] = scriptdata[a * 3 + 2] + 32767
  4129.         
  4130.         elseif obj and step < total and step >= 0
  4131.         {
  4132.             ! action
  4133.             routine = setscript[a * MAX_SCRIPT_STEPS + step * 2]
  4134.  
  4135.             ! object being acted upon
  4136.             b = setscript[a * MAX_SCRIPT_STEPS + step * 2 + 1]
  4137.        
  4138. #ifset DEBUG                        
  4139.             if debug_flags & D_SCRIPTS
  4140.             {
  4141.                 print "[Script for obj. "; 
  4142.                 print number obj; " ("; obj.name; "), step ";
  4143.                 print number (step + 1); ":  $"; \
  4144.                 hex routine; ", obj. ";
  4145.                 print number b; " ("; b.name; ")]"
  4146.             }
  4147. #endif
  4148.        
  4149.             scriptdata[a * 3 + 1] = step + 1
  4150.             tempactor = actor
  4151.             tempverb = verbroutine
  4152.             tempobject = object
  4153.             actor = obj
  4154.             verbroutine = routine
  4155.             object = b
  4156.             if not parent(actor).before
  4157.             {
  4158.                 if not actor.before
  4159.                 {
  4160.                     if not object.before
  4161.                     {
  4162.                         call routine(obj, b)
  4163.                         run actor.after
  4164.                     }
  4165.                 }
  4166.             }
  4167.             if actor in location:  actor is known
  4168.             actor = tempactor
  4169.             verbroutine = tempverb
  4170.             object = tempobject
  4171.         }
  4172.         elseif step >= 0
  4173.         {
  4174.             scriptdata[a * 3] = 0   ! clear this object's script
  4175.             if a = number_scripts - 1
  4176.                 number_scripts--
  4177.         }
  4178.     }
  4179.  
  4180. #endif  ! ifclear NO_SCRIPTS
  4181.  
  4182. }
  4183.  
  4184. #ifclear NO_SCRIPTS
  4185.  
  4186. !----------------------------------------------------------------------------
  4187. ! CancelScript(char)
  4188. ! immediately halts execution of the script for <char>
  4189. !
  4190. ! PauseScript(char)
  4191. ! suspends execution of the script for <char>
  4192. !
  4193. ! ResumeScript(char)
  4194. ! resumes execution of a paused script
  4195. !
  4196. ! SkipScript(char)
  4197. ! skips <char>'s script only for the next call to RunScripts
  4198.  
  4199. routine CancelScript(obj)
  4200. {
  4201.     local o
  4202.  
  4203.     o = FindScript(obj)
  4204.     if o = MAX_SCRIPTS
  4205.         return
  4206.     scriptdata[o * 3] = 0
  4207.     if o = number_scripts - 1
  4208.         number_scripts--
  4209.  
  4210. #ifset DEBUG                        
  4211.         if debug_flags & D_SCRIPTS
  4212.         {
  4213.             print "[Script for obj. "; 
  4214.             print number obj; " ("; obj.name; ") ";
  4215.             print "cancelled]"
  4216.         }
  4217. #endif
  4218.  
  4219.     return true
  4220. }
  4221.  
  4222. routine PauseScript(obj)
  4223. {
  4224.     local o
  4225.  
  4226.     o = FindScript(obj)
  4227.     if o = MAX_SCRIPTS
  4228.         return
  4229.     if scriptdata[o * 3 + 1] >= 0           ! current step
  4230.     {
  4231.         scriptdata[o * 3 + 1] = scriptdata[o * 3 + 1] - 32767
  4232.  
  4233. #ifset DEBUG                        
  4234.         if debug_flags & D_SCRIPTS
  4235.         {
  4236.             print "[Script for obj. "; 
  4237.             print number obj; " ("; obj.name; ") ";
  4238.             print "paused]"
  4239.         }
  4240. #endif
  4241.  
  4242.         return true
  4243.     }
  4244. }
  4245.  
  4246. routine ResumeScript(obj)
  4247. {
  4248.     local o
  4249.  
  4250.     o = FindScript(obj)
  4251.     if o = MAX_SCRIPTS
  4252.         return
  4253.     if scriptdata[o * 3 + 1] < 0            ! current step
  4254.     {
  4255.         scriptdata[o * 3 + 1] = scriptdata[o * 3 + 1] + 32767
  4256.  
  4257. #ifset DEBUG                        
  4258.         if debug_flags & D_SCRIPTS
  4259.         {
  4260.             print "[Script for obj. "; 
  4261.             print number obj; " ("; obj.name; ") ";
  4262.             print "resumed]"
  4263.         }
  4264. #endif
  4265.  
  4266.         return true
  4267.     }
  4268. }
  4269.  
  4270. routine SkipScript(obj)
  4271. {
  4272.     local o
  4273.  
  4274.     o = FindScript(obj)
  4275.     if o = MAX_SCRIPTS
  4276.         return
  4277.     if scriptdata[o * 3 + 2] >= 0           ! total number of steps
  4278.     {
  4279.         scriptdata[o * 3 + 2] = scriptdata[o * 3 + 2] - 32767
  4280.  
  4281. #ifset DEBUG                        
  4282.         if debug_flags & D_SCRIPTS
  4283.         {
  4284.             print "[Skipping script for obj. "; 
  4285.             print number obj; " ("; obj.name; ")]"
  4286.         }
  4287. #endif
  4288.  
  4289.         return true
  4290.     }
  4291. }
  4292.  
  4293.  
  4294. !----------------------------------------------------------------------------
  4295. ! BASIC CHARACTER VERB ROUTINES:
  4296. !----------------------------------------------------------------------------
  4297. ! LoopScript
  4298. ! may be used in a script to repeatedly return to the starting step; the 
  4299. ! usage is:  &LoopScript, 0
  4300.  
  4301. routine LoopScript(obj)
  4302. {        
  4303.     local o
  4304.  
  4305.     while scriptdata[o * 3] ~= obj and o < MAX_SCRIPTS:  o++
  4306.     if o = MAX_SCRIPTS
  4307.         return
  4308.     scriptdata[o * 3 + 1] = 0
  4309.  
  4310. #ifset DEBUG                        
  4311.     if debug_flags & D_SCRIPTS
  4312.     {
  4313.         print "[Looping script for obj. "; 
  4314.         print number obj; " ("; obj.name; ")]"
  4315.     }
  4316. #endif
  4317.  
  4318. }
  4319.  
  4320. !----------------------------------------------------------------------------
  4321. ! CharWait
  4322. ! Script usage: &CharWait, 0
  4323.  
  4324. routine CharWait(char)
  4325. {
  4326.  
  4327. #ifset DEBUG
  4328.     if debug_flags & D_SCRIPTS
  4329.         {print "["; CThe(char); IsorAre(char, true); " waiting in:  ";
  4330.         print capital parent(char).name; ".]"}
  4331. #endif
  4332.  
  4333.     return true
  4334. }
  4335.  
  4336. !----------------------------------------------------------------------------
  4337. ! CharMove
  4338. ! Script usage:  &CharMove, <direction object>
  4339.  
  4340. routine CharMove(char, dir)
  4341. {
  4342.     local newroom
  4343.  
  4344. #ifclear NO_OBJLIB
  4345.  
  4346.     general = 1                     ! for signalling a character move
  4347.                     ! to, for example, door.door_to
  4348.     
  4349.     newroom = parent(char).(dir.dir_to)
  4350.  
  4351.     if char in location and general = 1     ! door.door_to sets general
  4352.                         ! to 2 if it prints a message
  4353.     {
  4354.         Message(&CharMove, 1, char, dir)
  4355.         event_flag = true
  4356.     }
  4357.     elseif char in location
  4358.         event_flag = true
  4359.     
  4360.     move char to newroom
  4361.     
  4362. #ifset DEBUG        
  4363.     if debug_flags & D_SCRIPTS
  4364.     {
  4365.         print "["; CThe(char); IsorAre(char, true); " now in:  ";
  4366.         print capital parent(char).name; ".]"
  4367.     }
  4368. #endif
  4369.  
  4370.     if char in location and general = 1
  4371.     {
  4372.         Message(&CharMove, 2, char, dir)
  4373.         event_flag = true
  4374.     }
  4375.     elseif char in location
  4376.         event_flag = true
  4377.  
  4378.     general = 0                     ! always reset it
  4379.  
  4380. #endif  ! ifclear NO_OBJLIB
  4381.  
  4382.     run parent(char).after
  4383.     
  4384.     return true
  4385. }
  4386.  
  4387. !----------------------------------------------------------------------------
  4388. ! CharGet
  4389. ! Script usage:  &CharGet, <object>
  4390.  
  4391. routine CharGet(char, obj)
  4392. {
  4393.     if FindObject(obj, parent(char)) = 1
  4394.     {
  4395.         if Acquire(char, obj)
  4396.             if char in location 
  4397.             {
  4398.                 Message(&CharGet, 1, char, obj)
  4399.                 event_flag = true
  4400.             }
  4401.             return true
  4402.     }
  4403. }
  4404.  
  4405. !----------------------------------------------------------------------------
  4406. ! CharDrop
  4407. ! Script usage:  &CharDrop, <object>
  4408.  
  4409. routine CharDrop(char, obj)
  4410. {
  4411.     move obj to parent(char)
  4412.     char.holding = char.holding - obj.size
  4413.     if char in location 
  4414.     {
  4415.         Message(&CharDrop, 1, char, obj)
  4416.         event_flag = true
  4417.     }
  4418.     return true
  4419. }
  4420.  
  4421. #endif  ! ifclear NO_SCRIPTS
  4422.  
  4423.  
  4424. !\
  4425. *****************************************************************************
  4426.  
  4427. LIBRARY MESSAGES
  4428.  
  4429. Most of the text printed by the library is generated by the Message routine.
  4430. To replace all of the default responses, REPLACE the Message routine.  To
  4431. replace one or more responses, REPLACE the NewMessages routine, and return
  4432. true for any replacement message that is provided; if NewMessages returns a
  4433. false value, Message prints the default response.
  4434.  
  4435. NOTE:  Other routines in HUGOLIB.H that print text independent of the
  4436. Message routine are:  PrintEndGame, PrintScore, ParseError, PrintStatusLine,
  4437. HoursMinutes, The, CThe, Art, CArt, IsorAre, MatchSubject, NumberWord,
  4438. DigitWord, DarkWarning, ObjectIs, and various debugging messages.
  4439.  
  4440. *****************************************************************************
  4441. \!
  4442.  
  4443. !----------------------------------------------------------------------------
  4444. ! Message(&routine, number)
  4445. ! prints message <number> for <routine>
  4446. !
  4447. ! Message (&routine, number, var1, var2)
  4448. ! where one or two variables--which may be objects or any other value--
  4449. ! are used by message <number> for <routine>
  4450.  
  4451. routine Message(r, num, a, b)
  4452. {
  4453.     ! Check first to see if the NewMessages routine provides a 
  4454.     ! replacement message:
  4455.     if NewMessages(r, num, a, b):  return
  4456.  
  4457.     select r
  4458.     
  4459.     case &EndGame
  4460.     {
  4461.         select num
  4462.         case 1
  4463.         {
  4464.             print "\nThe game has ended.  Do you want to RESTART, 
  4465.                 RESTORE a saved game, ";
  4466. #ifclear NO_UNDO
  4467.             if not UNDO_OFF         ! if not otherwise overridden
  4468.                 print "UNDO your last turn, ";
  4469. #endif
  4470.             print "or QUIT? ";
  4471.         }
  4472.         case 2
  4473.         {
  4474.             print "Enter RESTART, RESTORE, ";
  4475. #ifclear NO_UNDO
  4476.             if not UNDO_OFF
  4477.                 print "UNDO, "; 
  4478. #endif
  4479.             print "or QUIT: ";
  4480.         }
  4481.     }
  4482.  
  4483.     case &Parse
  4484.     {
  4485.         select num
  4486.         case 1:  print CThe(player); \
  4487.                 MatchPlural(player, "doesn't", "don't"); \
  4488.                 " need to refer to that."
  4489.         case 2:  print "(Assuming you mean";
  4490.         case 3:  print ", respectively";
  4491.     }
  4492.     
  4493.     case &Speakto
  4494.     {
  4495.         if a = 0:  a = object   ! Speakto messages are sometimes
  4496.                     ! co-opted by verb routines
  4497.         select num
  4498.         case 1:  print CThe(player); " probably ought not to waste
  4499.                 time talking to "; player.pronoun #4; "."
  4500.         case 2:  print CThe(a); IsorAre(a, true); " listening."
  4501.         case 3:  print CThe(a); " nod"; MatchSubject(a); \
  4502.                 " hello to "; The(player, true); "."
  4503.         case 4:  print CThe(a); " ignore"; MatchSubject(a); " "; \
  4504.                 The(player, true); "."
  4505.     }
  4506.  
  4507.     case &DescribePlace
  4508.     {
  4509.         select num
  4510.         case 1:  print "It's too dark to see anything."
  4511.         case 2:  print "There"; IsorAre(a, true); " "; Art(a); \
  4512.                 " here."
  4513.     }
  4514.  
  4515.     case &WhatsIn
  4516.     {
  4517.         select num
  4518.         case 1
  4519.         {
  4520.             print CThe(player); IsorAre(player, true); " ";
  4521.             if list_count < a
  4522.                 print "also ";
  4523.             print "carrying";
  4524.         }
  4525.         case 2
  4526.         {
  4527.             if FORMAT & USECHARNAMES_F
  4528.                 CArt(a)
  4529.             else
  4530.                 print capital a.pronoun;
  4531.             if list_count < b
  4532.                 print " also";
  4533.             print MatchPlural(a, "has", "have");
  4534.         }
  4535.         case 3
  4536.         {
  4537.             print "Also ";
  4538.             if a.prep
  4539.                 print a.prep; " ";
  4540.             elseif a is platform
  4541.                 print "sitting on ";
  4542.             else
  4543.                 print "inside ";
  4544.         }
  4545.         case 4
  4546.         {
  4547.             if a.prep
  4548.                 print capital a.prep; " ";
  4549.             elseif a is platform
  4550.                 print "Sitting on ";
  4551.             else
  4552.                 print "Inside ";
  4553.         }
  4554.     }
  4555.  
  4556.     case &CheckReach
  4557.     {
  4558.         select num
  4559.         case 1
  4560.         {
  4561.             print "Except that "; The(parent(a)); \
  4562.                 MatchPlural(parent(a), "has", "have"); \
  4563.                 " "; The(a); "."
  4564.         }
  4565.         case 2
  4566.         {
  4567.             print "Except that "; The(parent(a)); \
  4568.                 MatchPlural(parent(a), "doesn't", "don't"); \
  4569.                 " want to give "; The(player, true); \
  4570.                 " "; The(a); "."
  4571.         }
  4572.         case 3:  print CThe(player); " can't reach "; The(a); \
  4573.                 " from "; The(parent(player)); "."
  4574.     }
  4575.     
  4576.     case &YesorNo:  print "Please answer YES or NO: ";
  4577.  
  4578. #ifclear NO_MENUS
  4579.     case &Menu
  4580.     {
  4581.         print "[N]ext item"; to (linelength - 11); "[Q]uit menu"
  4582.         print "[P]revious item"; to (linelength - 17); 
  4583.         print "[Enter] to select"
  4584.     }
  4585. #endif
  4586.  
  4587. #ifclear NO_VERBS
  4588.  
  4589.     case &DoVague:
  4590.     {
  4591.         print "Be a little more specific about what you'd like ";
  4592.         if player_person ~= 2
  4593.             print CThe(player, true); " ";
  4594.         print "to "; word[1]; "."
  4595.     }
  4596.  
  4597.     case &DoLook
  4598.     {
  4599.         select num
  4600.         case 1:  print "It's too dark to see anything."
  4601.         case 2:  print CThe(object); " look"; MatchSubject(object); \
  4602.                 " just like "; The(player); " would expect."
  4603.     }
  4604.  
  4605.     case &DoLookIn
  4606.     {
  4607.         select num
  4608.         case 1:  print CThe(object); IsorAre(object, true); " closed."
  4609.         case 2:  print CThe(object); IsorAre(object, true); " empty."
  4610.     }
  4611.  
  4612.     case &DoLookThrough
  4613.     {
  4614.         select num
  4615.         case 1:  print "Through "; Art(object); " "; The(player); \
  4616.             " can see ";
  4617.         case 2:  print CThe(player); " can't see through that."
  4618.     }
  4619.  
  4620.     case &DoLookUnder:  print CThe(player); \
  4621.                 MatchPlural(player, "doesn't", "don't"); \
  4622.                 " find anything "; word[2]; " "; \
  4623.                 The(object); "."
  4624.  
  4625.     case &DoWait:  "Time passes..."
  4626.  
  4627.     case &DoWaitforChar
  4628.     {
  4629.         select num
  4630.         case 1:
  4631.         {
  4632.             print CThe(object); IsorAre(object, true); \
  4633.                 " right here.";
  4634.             if player_person = 2:  print "  Good detective work."
  4635.             print newline
  4636.         }
  4637.         case 2
  4638.         {
  4639.             print CThe(object); \
  4640.                 MatchPlural(object, "has", "have"); \
  4641.                 " arrived.  ";
  4642.             if STATUSTYPE = 2
  4643.                 print "It is now "; HoursMinutes(counter);
  4644.             print newline
  4645.         }
  4646.         case 3
  4647.         {
  4648.             print CThe(player); \
  4649.                 MatchPlural(player, "has", "have"); \
  4650.                 " been waiting ";
  4651.             select STATUSTYPE
  4652.                 case 2
  4653.                     print "an hour";
  4654.                 case else
  4655.                     print "for twenty turns";
  4656.             print ", and "; The(object); " still"; \
  4657.                 MatchPlural(object, "hasn't", "haven't");
  4658.                 " arrived."
  4659.         }
  4660.     }
  4661.  
  4662.     case &DoWaitUntil
  4663.     {
  4664.         select num
  4665.         case 1:  print "Wow.  Time flies."
  4666.         case 2:
  4667.         {
  4668.             if player_person = 2
  4669.                 print CThe(player); IsorAre(player); \
  4670.                     " ahead of your time."
  4671.             else
  4672.                 print "You're getting ahead of "; \
  4673.                     The(player, true); "."
  4674.         }
  4675.         case 3
  4676.         {
  4677.             select STATUSTYPE
  4678.             case 2: print "It is now "; HoursMinutes(counter)
  4679.             case else: print "It is now turn "; number object; "."
  4680.         }
  4681.     }
  4682.  
  4683.     case &KeepWaiting:
  4684.     {
  4685.         print "\nDo you want ";
  4686.         if player_person ~= 2:  print The(player, true); " ";
  4687.         print "to keep waiting (YES or NO)? ";
  4688.     }
  4689.  
  4690.     case &DoTalk:
  4691.     {
  4692.         print "Try ";
  4693.         if player_person ~= 2
  4694.             print "having "; The(player, true); " ask or tell";
  4695.         else:  print "asking or telling";
  4696.         print " someone about something in particular."
  4697.     }
  4698.  
  4699.     case &DoAsk
  4700.     {
  4701.         select num
  4702.         case 1:
  4703.         {
  4704.             print "Try ";
  4705.             if player_person ~= 2
  4706.                 print "having "; The(player, true); " ask";
  4707.             else:  print "asking";
  4708.             print " someone about something in particular."
  4709.         }
  4710.         case 2:  print "Talking to"; player.pronoun #4; " isn't a
  4711.             big step forward."
  4712.         case 3:  print "Hopefully "; The(player); " know"; \
  4713.             MatchSubject(player); " as much as anyone."
  4714.         case 4
  4715.         {
  4716.             print CThe(object); " would probably rather 
  4717.                 not talk about "; object.pronoun #4; "."
  4718.         }
  4719.         case 5
  4720.         {
  4721.             print CThe(object); " glance"; MatchSubject(object); \
  4722.                 " toward "; The(xobject); ".  "; \
  4723.                 capital object.pronoun; " would probably 
  4724.                 rather not say anything with "; \
  4725.                 The(xobject); " right here."
  4726.         }
  4727.         case 6
  4728.         {
  4729.             print CThe(object); \
  4730.                 MatchPlural(object, "doesn't", "don't"); \
  4731.                 " seem to know anything about "; \
  4732.                 The(xobject); "."
  4733.         }
  4734.     }
  4735.  
  4736.     case &DoAskQuestion
  4737.         print CThe(player); MatchPlural(object, "isn't", "aren't"); \
  4738.             " talking to anybody."
  4739.  
  4740.     case &DoTell
  4741.     {
  4742.         select num
  4743.         case 1:
  4744.         {
  4745.             print "Try ";
  4746.             if player_person ~= 2
  4747.                 print "having "; The(player, true); " tell";
  4748.             else:  print "telling";
  4749.             print " someone about something in particular."
  4750.         }
  4751.         case 2:  print CThe(object); IsorAre(object, true); " not 
  4752.             particularly interested in "; The(xobject); "."
  4753.     }
  4754.  
  4755.     case &DoListen
  4756.     {
  4757.         select num
  4758.         case 1:
  4759.         {
  4760.             print "Be a little more specific about exactly what
  4761.                 you'd like ";
  4762.             if player ~= 2:  print The(player, true); " ";
  4763.             print "to listen to."
  4764.         }
  4765.         case 2:  print CThe(object); IsorAre(object, true); " not 
  4766.                 making a sound."
  4767.     }
  4768.  
  4769.     case &DoGo
  4770.     {
  4771.         select num
  4772.         case 1:  print CThe(obstacle); " stop"; \
  4773.             MatchSubject(obstacle); " you from going anywhere."
  4774.         case 2:  print CThe(player); " can't go that way."
  4775.         case 3
  4776.         {
  4777.             print CThe(player); " will have to get ";
  4778.             if parent(player).prep #2
  4779.                 print parent(player).prep #2; " ";
  4780.             else
  4781.                 print "out ";
  4782.             print "of "; The(parent(player)); " first."
  4783.         }
  4784.     }
  4785.  
  4786.     case &DoEnter
  4787.     {
  4788.         select num
  4789.         case 1:
  4790.         {
  4791.             print "Be a little more specific about where you'd
  4792.                 like ";
  4793.             if player ~= 2:  print The(player, true); " ";
  4794.             print "to "; word[1]; "."
  4795.         }
  4796.         case 2:  
  4797.         {
  4798.             print CThe(player); " can't ";
  4799.             if object is platform
  4800.                 print "get on ";
  4801.             else
  4802.                 print "enter ";
  4803.             print The(object); "."
  4804.         }
  4805.         case 3:  print "A bit redundant, don't you think?"
  4806.         case 4
  4807.         {
  4808.             print CThe(player); " get"; MatchSubject(player); " ";
  4809.             if object.prep
  4810.                 print object.prep;
  4811.             else
  4812.                 print "into";
  4813.             print " "; The(object); "."
  4814.         }
  4815.     }
  4816.  
  4817.     case &DoExit
  4818.     {
  4819.         select num
  4820.         case 1
  4821.         {
  4822.             print CThe(player); IsorAre(player); " not ";
  4823.             if object.prep
  4824.                 print object.prep;
  4825.             else
  4826.                 print "in"; 
  4827.             print " "; The(object); "."
  4828.         }
  4829.         case 2
  4830.         {
  4831.             print CThe(player); " get"; MatchSubject(player); " ";
  4832.             if object.prep #2 
  4833.                 print object.prep #2;
  4834.             else
  4835.                 print "out";
  4836.             print " of "; The(object); "."
  4837.         }
  4838.     }
  4839.  
  4840.     case &DoInventory:
  4841.         print CThe(player); IsorAre(player); " not carrying anything."
  4842.  
  4843.     case &DoClose
  4844.     {
  4845.         select num
  4846.         case 1:  print CThe(player); " can't close "; The(object); "."
  4847.         case 2:  print capital object.pronoun; IsorAre(object); \
  4848.                 " already closed."
  4849.         case 3:  print "Closed."
  4850.         case 4:  print "\nEverything goes dark."
  4851.  
  4852.     }
  4853.  
  4854.     case &DoOpen
  4855.     {
  4856.         select num
  4857.         case 1:  print CThe(player); " can't open "; The(object); "."
  4858.         case 2:  print capital object.pronoun; IsorAre(object); \
  4859.                 " already open."
  4860.         case 3:  print CThe(object); IsorAre(object, true); " locked."
  4861.         case 4:  print "Opened."
  4862.     }
  4863.  
  4864.     case &DoMove:  print CThe(player); " can't move "; The(object); "."
  4865.  
  4866.     case &DoGet
  4867.     {
  4868.         select num
  4869.         case 1:  print CThe(player); " already"; \
  4870.             MatchPlural(player, "has", "have"); " that."
  4871.         case 2:  print "This is not progress "; CThe(player); \
  4872.             IsorAre(player, true); " making."
  4873.         case 3:  print CThe(object); " probably wouldn't be too big 
  4874.                 on that idea."
  4875.         case 4
  4876.         {
  4877.             print CThe(parent(object)); \
  4878.                 MatchPlural(object, "doesn't", "don't"); \
  4879.                 " want to give "; The(object); " to "; \
  4880.                 The(player, true); "."
  4881.         }
  4882.         case 5:  print CThe(parent(object)); \
  4883.             IsOrAre(parent(object), true); " closed."
  4884.         case 6
  4885.         {
  4886.             print CThe(player); " can't take "; The(object); \
  4887.                 " while "; player.pronoun; IsorAre(player);
  4888.             if object.prep:  print object.prep
  4889.             elseif object is platform:  print "in"
  4890.             else:  print "on"
  4891.             if object is plural:  print "them."
  4892.             else:  print "it."
  4893.         }
  4894.         case 7:  print CThe(player); " can't take that."
  4895.         case 8:  print "Taken."
  4896.         case 9:  print CThe(player); IsorAre(player); " carrying
  4897.             too much to take that."
  4898.     }
  4899.  
  4900.     case &DoDrop
  4901.     {
  4902.         select num
  4903.         case 1:  print CThe(player); " will have to take "; \
  4904.             The(object); " off first."
  4905.         case 2:  print "Dropped."
  4906.     }
  4907.  
  4908.     case &DoPutonGround
  4909.     {
  4910.         print CThe(player); IsorAre(player); " not ";
  4911.         if xobject.prep
  4912.             print xobject.prep;
  4913.         else
  4914.             print "in";
  4915.         print " "; The(xobject); "."
  4916.     }
  4917.  
  4918.     case &DoPutIn
  4919.     {
  4920.         select num
  4921.         case 1:
  4922.         {
  4923.             print "You'll have to be a little more specific
  4924.                 about exactly with what you'd like ";
  4925.             if player ~= 2:  print The(player, true); " ";
  4926.             print "to do that."
  4927.         }
  4928.         case 2:  print CThe(xobject); IsorAre(xobject, true); \
  4929.                 " closed."
  4930.         case 3:  print CThe(player); " can't do that."
  4931.         case 4:  print "Trying to bend the laws of physics, are we?"
  4932.         case 5
  4933.         {
  4934.             print CThe(player); " put"; MatchSubject(player); \
  4935.                 " "; The(object);
  4936.             if xobject.prep
  4937.                 print " "; xobject.prep; " ";
  4938.             elseif xobject is platform
  4939.                 print " on ";
  4940.             else
  4941.                 print " in ";
  4942.             print The(xobject); "."
  4943.         }
  4944.         case 6
  4945.         {
  4946.             print "There's no room ";
  4947.             if xobject.prep
  4948.                 print xobject.prep; " ";
  4949.             elseif xobject is platform
  4950.                 print "on ";
  4951.             else
  4952.                 print "in ";
  4953.             print The(xobject); "."
  4954.         }
  4955.     }
  4956.  
  4957.     case &DoEmpty
  4958.     {
  4959.         select num
  4960.         case 1
  4961.         {
  4962.             print CThe(object); IsorAre(object, true); \
  4963.                 " closed."
  4964.         }
  4965.         case 2:  print CThe(object); IsorAre(object, true); \
  4966.                 " already empty."
  4967.         case 3:  print CThe(player); " can't move that."
  4968.     }
  4969.  
  4970.     case &DoGive
  4971.     {
  4972.         select num
  4973.         case 1:
  4974.         {
  4975.             print "Try ";
  4976.             if player_person ~= 2
  4977.                 print "having "; The(player, true); " give";
  4978.             else:  print "giving";
  4979.             print " something to someone in particular."
  4980.         }
  4981.         case 2:
  4982.         {
  4983.             print "Not quite sure what you hope ";
  4984.             if player ~= 2:  print The(player, true); " will";
  4985.             else:  print "to";
  4986.             print " accomplish with that."
  4987.         }
  4988.         case 3:
  4989.         {
  4990.             if player = 1, 2: print capital player.pronoun #3;
  4991.             else:  print CThe(player); "'s";
  4992.             print "kind gesture goes unnoticed by "; \
  4993.                 The(xobject); "."
  4994.         }
  4995.         case 4
  4996.         {
  4997.             print CThe(xobject); 
  4998.             if xobject is not unfriendly
  4999.                 print " politely"; 
  5000.             print " refuse"; MatchSubject(xobject); "."
  5001.         }
  5002.         case 5:  print "(taking "; The(object); " first)"
  5003.     }
  5004.  
  5005.     case &DoShow
  5006.     {
  5007.         select num
  5008.         case 1:
  5009.         {
  5010.             print "Try ";
  5011.             if player_person ~= 2
  5012.                 print "having "; The(player, true); " show";
  5013.             else:  print "showing";
  5014.             print " something to someone in particular."
  5015.         }
  5016.         case 2:  print "Showing "; Art(object); "to "; The(xobject); \
  5017.                 " doesn't accomplish a whole lot."
  5018.         case 3:  print CThe(xobject); " ignore"; \
  5019.                 MatchSubject(xobject); " "; The(object); "."
  5020.     }
  5021.  
  5022.     case &DoWear
  5023.     {
  5024.         select num
  5025.         case 1:  print CThe(player); " can't wear "; The(object); "."
  5026.         case 2:  print CThe(player); IsorAre(player); " already
  5027.             wearing that."
  5028.         case 3:  print CThe(player); " put"; MatchSubject(player); \
  5029.             " on "; The(object); "."
  5030.     }
  5031.  
  5032.     case &DoTakeOff
  5033.     {
  5034.         select num
  5035.         case 1:  print CThe(player); IsorAre(player); " not
  5036.             wearing that."
  5037.         case 2:  print CThe(player); " can't do that with "; \
  5038.             The(object); "."
  5039.         case 3:  print CThe(player); " take"; MatchSubject(player); \
  5040.             " off "; The(object); "."
  5041.     }
  5042.  
  5043.     case &DoSwitchOn
  5044.     {
  5045.         select num
  5046.         case 1:  print capital object.pronoun; IsorAre(object); \
  5047.                 " already turned on."
  5048.         case 2:  print "Switched on."
  5049.     }
  5050.  
  5051.     case &DoSwitchOff
  5052.     {
  5053.         select num
  5054.         case 1:  print capital object.pronoun; IsorAre(object); \
  5055.                 " already turned off."
  5056.         case 2:  print "Switched off."
  5057.     }
  5058.  
  5059.     case &DoUnlock
  5060.     {
  5061.         select num
  5062.         case 1:  print "That doesn't seem to do the trick."
  5063.         case 2:  print CThe(player); IsorAre(player); " not holding
  5064.             any key that fits."
  5065.         case 3:  print capital object.pronoun; IsorAre(object); \
  5066.                 " already unlocked."
  5067.         case 4
  5068.         {
  5069.             if not xobject and object.key_object
  5070.                 print "(with "; The(object.key_object); ")"
  5071.             print "Unlocked."
  5072.         }
  5073.     }
  5074.  
  5075.     case &DoLock
  5076.     {
  5077.         select num
  5078.         case 1:  print capital object.pronoun; IsorAre(object); \
  5079.                 " already locked."
  5080.         case 2:  print CThe(player); " will have to close "; \
  5081.             object.pronoun; " first."
  5082.         case 3
  5083.         {
  5084.             if not xobject and object.key_object
  5085.                 print "(with "; The(object.key_object); ")"
  5086.             print "Locked."
  5087.         }
  5088.     }
  5089.  
  5090.     case &DoEat:  print CThe(player); " can't eat "; The(object); "."
  5091.  
  5092.     case &DoDrink:  print CThe(player); " can't drink "; The(object); "."
  5093.  
  5094.     case &DoHit:  print "Venting "; player.pronoun #3; " frustrations
  5095.             on "; The(object); " won't accomplish much."
  5096.  
  5097. #endif  ! ifclear NO_VERBS
  5098.  
  5099. #ifclear NO_XVERBS
  5100.  
  5101.     case &DoHello:  print "And to you."
  5102.  
  5103.     case &DoBrief:  print "Brief descriptions."
  5104.     case &DoSuperBrief:  print "Superbrief descriptions."
  5105.     case &DoVerbose:  print "Verbose descriptions."
  5106.  
  5107.     case &DoDisplay
  5108.     {
  5109.         select num
  5110.         case 1:  print "Tall listings."
  5111.         case 2:  print "Wide listings."
  5112.         case 3:  print "Type \"display tall\" or \"display wide\" to 
  5113.                 alter the way objects are listed."
  5114.     }
  5115.  
  5116.     case &DoSave
  5117.     {
  5118.         select num
  5119.         case 1:  print "Saved."
  5120.         case 2:  print "Unable to save."
  5121.     }
  5122.  
  5123.     case &DoRestore
  5124.     {
  5125.         select num
  5126.         case 1:  print "Restored."
  5127.         case 2:  print "Unable to restore."
  5128.     }
  5129.  
  5130.     case &DoQuit:  print "Are you sure you want to quit (YES or NO)? ";
  5131.  
  5132.     case &DoRestart
  5133.     {
  5134.         select num
  5135.         case 1:  print "Are you sure you want to restart (YES or 
  5136.                 NO)? ";
  5137.         case 2:  print "Unable to restart."
  5138.     }
  5139.  
  5140.     case &DoScriptOnOff
  5141.     {
  5142.         select num
  5143.         case 1:  print "Unable to begin transcription."
  5144.         case 2:  print "Transcription on."
  5145.         case 3:  print "Unable to end transcription."
  5146.         case 4:  print "Transcription off."
  5147.     }
  5148.  
  5149. #ifclear NO_RECORDING
  5150.     case &DoRecordOnOff
  5151.     {
  5152.         select num
  5153.         case 1:  print "Unable to begin command playback."
  5154.         case 2:  print "Command playback beginning."
  5155.         case 3:  print "Unable to begin command recording."
  5156.         case 4:  print "Command recording on."
  5157.         case 5:  print "Unable to end command recording."
  5158.         case 6:  print "Command recording off."
  5159.     }
  5160. #endif
  5161.  
  5162.     case &DoScore:  print "Nobody's keeping score."
  5163.  
  5164.     case &DoUndo:  print "Unable to undo."
  5165.  
  5166. #endif  ! ifclear NO_XVERBS
  5167.  
  5168. #ifclear NO_SCRIPTS
  5169. #ifclear NO_OBJLIB
  5170.     case &CharMove
  5171.     {
  5172.         select num
  5173.         case 1
  5174.         {
  5175.             print "\n"; CThe(a); " head"; MatchSubject(a); " ";
  5176.             if b = u_obj or b = d_obj
  5177.                 print b.name; "ward."
  5178.             else
  5179.             {
  5180.                 print "off to the ";
  5181.                 print b.name; "."
  5182.             }
  5183.         }
  5184.         case 2
  5185.         {
  5186.             print "\n"; CThe(a); " arrive"; MatchSubject(a); \ 
  5187.                 " from ";
  5188.             if b ~= u_obj and b ~= d_obj
  5189.                 print "the "; (b.dir_from).name; "."
  5190.             elseif b = u_obj
  5191.                 print "below."
  5192.             else
  5193.                 print "above."
  5194.         }
  5195.     }
  5196. #endif  ! ifclear NO_OBJLIB
  5197.  
  5198.     case &CharGet:  print "\n"; CThe(a); " pick"; MatchSubject(a); \
  5199.             " up "; The(b); "."
  5200.  
  5201.     case &CharDrop:  print "\n"; CThe(a); " put"; MatchSubject(a); \
  5202.             " down "; The(b); "."
  5203. #endif  ! ifclear NO_SCRIPTS
  5204. }
  5205.  
  5206. routine NewMessages(r, num, a, b)       ! The NewMessages routine may be
  5207. {                                       ! REPLACED, and should return true
  5208.     return false                    ! if a replacement message <num>
  5209. }                                       ! exists for routine <r>
  5210.  
  5211.  
  5212. #set _COMPILING_HUGOLIB
  5213.  
  5214. !----------------------------------------------------------------------------
  5215. ! Include object library unless otherwise specified
  5216.  
  5217. #ifclear NO_OBJLIB
  5218. #include "objlib.h"
  5219. #endif
  5220.  
  5221. !----------------------------------------------------------------------------
  5222. ! Include verb stub routines if specified
  5223.  
  5224. #ifset VERBSTUBS
  5225. #include "verbstub.h"
  5226. #endif
  5227.  
  5228. !----------------------------------------------------------------------------
  5229. ! Include debugging routines if specified
  5230.  
  5231. #ifset DEBUG
  5232. #include "hugofix.h"
  5233. #endif
  5234.  
  5235. #clear _COMPILING_HUGOLIB
  5236. #set _HUGOLIB_DEFINED
  5237.  
  5238. !----------------------------------------------------------------------------
  5239. ! NOTE:  In addition to the flags VERBSTUBS and DEBUG which are used to 
  5240. ! include additional library files, a number of compiler flags can be set 
  5241. ! to exclude portions of HUGOLIB.H.  These are:  NO_AUX_MATH, NO_FONTS,
  5242. ! NO_FUSES, NO_MENUS, NO_OBJLIB, NO_RECORDING, NO_SCRIPTS, NO_STRING_ARRAYS, 
  5243. ! NO_VERBS, and NO_XVERBS.
  5244. !----------------------------------------------------------------------------
  5245.  
  5246.